문제

Microsoft Dynamics CRM에서 실험을하고 있습니다. 당신은 웹 서비스를 통해 그것과 상호 작용하고 내 프로젝트에 대한 웹 참조를 추가했습니다. 웹 서비스 인터페이스는 매우 풍부하며 생성 된 "Reference.cs"는 약 90k LOC입니다.

콘솔 응용 프로그램에서 웹 참조를 사용하고 있습니다. 나는 종종 무언가를 바꾸고, 다시 컴파일하고, 달린다. 컴파일은 빠르지 만 웹 서비스 참조를 새롭게하는 것은 매우 느립니다. 약 15-20 초가 소요됩니다. CrmService service = new CrmService(); 프로파일 링은 항상 soaphttpclientProtocol 생성자에 소비된다는 것을 보여줍니다.

범인은 분명히 XML 직렬화 코드 (위에서 언급 한 90K LOC에 포함되지 않음)가 런타임에 생성되기 전에 생성된다는 사실입니다. 이것은 생성자 호출 중에 발생합니다. 주위를 놀리고 시도 할 때 기다리는 것은 다소 실망 스럽습니다.

SGEN.EXE, NGEN 및 XGENPLUS (몇 시간이 걸리고 500MB의 추가 코드를 생성 함)의 다양한 조합을 시도했지만 소용이 없습니다. Crmservice 인스턴스가 필요할 때 접시를 준비 할 수있는 Windows 서비스를 구현하는 것을 고려했지만 과도하게 보입니다.

어떤 아이디어?

도움이 되었습니까?

해결책

다음은 찢어졌습니다 이것 VMware 포럼의 스레드 :

안녕 여러분,

우리는 sgen.exe가 작동한다는 것을 알았습니다. 이 스레드에서 우리가 놓친 시리얼 라이저 DLL을 사전 생성하는 것 외에 몇 가지 추가 단계가 있습니다. 자세한 지침은 다음과 같습니다

문제

.NET에서 VIM 2.0 SDK를 사용하는 경우 VimService 클래스를 인스턴스화하는 데 오랜 시간이 걸립니다. (Vimservice 클래스는 'wsdl.exe vim.wsdl vimservice.wsdl'을 실행하여 생성 된 프록시 클래스입니다.

다시 말해, 다음 코드 줄은 다음과 같습니다.

_service = new VimService();

실행하는 데 약 50 초가 걸릴 수 있습니다.

원인

분명히 .net XmlSerializer 사용 System.Xml.Serialization.* 런타임에 직렬화 코드를 생성하기 위해 프록시 클래스에 주석을 달라는 속성. Vimservice.cs의 코드와 마찬가지로 프록시 클래스가 많고 큰 경우 직렬화 코드의 생성은 오랜 시간이 걸릴 수 있습니다.

해결책

이것은 Microsoft .NET 시리얼 라이저의 작동 방식에 알려진 문제입니다.

다음은 MSDN 이이 문제를 해결하는 것에 대해 제공하는 몇 가지 참조입니다.

http://msdn2.microsoft.com/en-us/library/bk3w6240.aspx http://msdn2.microsoft.com/en-us/library/system.xml.serialization.xmlserializerassemblyattribute.aspx

불행히도, 위의 참조 중 어느 것도 문제에 대한 완전한 해결책을 설명하지 않습니다. 대신 XML 직렬화 코드를 사전 생성하는 방법에 중점을 둡니다.

완전한 수정에는 다음 단계가 포함됩니다.

  1. 사전 생성 된 XML 시리얼 라이저 코드로 어셈블리 (A A DLL) 작성

  2. System.xml.serialization에 대한 모든 참조를 제거하십시오.* 프록시 코드의 속성 (예 : vimservice.cs 파일).

  3. XMLSerializerAsSemblyAttribute와 함께 기본 프록시 클래스에 주석을 달아 XML 세리어 라이저 어셈블리가 위치하는 위치를 가리 키십시오.

2 단계를 건너 뛰면 인스턴스화 시간이 20% 만 개선됩니다. VimService 수업. 1 단계 또는 3 단계를 건너 뛰면 잘못된 코드가됩니다. 세 단계 모두 98% 개선이 이루어집니다.

단계별 지침은 다음과 같습니다.

시작하기 전에 .NET Verison 2.0 도구를 사용하고 있는지 확인하십시오. 이 솔루션은 SGEN 도구와 XmlSerializationAssemblyAttribute .NET의 버전 2.0에서만 사용할 수 있습니다

  1. wsdl.exe를 사용하여 wsdl에서 vimservice.cs 파일을 생성하십시오.

    wsdl.exe vim.wsdl vimService.wsdl

    이것은 현재 디렉토리에서 vimservice.cs 파일을 출력합니다.

  2. vimservice.cs를 라이브러리로 컴파일합니다

    csc /t:library /out:VimService.dll VimService.cs

  3. SGEN 도구를 사용하여 XML 시리얼 라이저를 사전 생성하고 컴파일하십시오.

    sgen /p VimService.dll

    이것은 현재 디렉토리에서 vimservice.xmlserializers.dll을 출력합니다

  4. vimservice.cs 파일로 돌아가서 모두 제거하십시오 System.Xml.Serialization.* 속성. 코드 코드가 크기 때문에이를 달성하는 가장 좋은 방법은 일부 정규식 대체 도구를 사용하는 것입니다. 모든 속성이 스스로 줄에 나타나는 것은 아니기 때문에이 작업을 수행 할 때 조심하십시오. 일부는 메소드 선언의 일부로 출시되었습니다.

    이 단계가 어려워지면 여기에 단순화 된 방법이 있습니다.

    C#을 쓰고 있다고 가정하면 다음 문자열에서 전역 교체를 수행하십시오.

    [System.Xml.Serialization.XmlIncludeAttribute

    그리고 그것을 대체합니다.

    // [System.Xml.Serialization.XmlIncludeAttribute

    이것은 없을 것입니다 Xml.Serialization 촉진하여 둔화를위한 가장 큰 원인 인 속성. 다른 .NET 언어를 사용하는 경우 해당 언어의 구문에 따라 교체 된 문자열을 접두사로 수정하십시오. 이 단순화 된 접근 방식은 당신이 얻을 수있는 대부분의 속도를 얻을 수 있습니다. 나머지 XML.serialization 속성을 제거하면 추가 0.2 초의 속도 만 달성됩니다.

  5. vimservice.cs의 vimservice 클래스에 다음 속성을 추가하십시오.

    [System.Xml.Serialization.XmlSerializerAssemblyAttribute(AssemblyName = "VimService.XmlSerializers")]

    당신은 다음과 같은 것으로 끝나야합니다.

    // ... Some code here ... [System.Xml.Serialization.XmlSerializerAssemblyAttribute(AssemblyName = "VimService.XmlSerializers")] public partial class VimService : System.Web.Services.Protocols.SoapHttpClientProtocol { // ... More code here

  6. Vimserice.dll 라이브러리를 재생합니다

    csc /t:library /out:VimService.dll VimService.cs

  7. 이제 응용 프로그램에서 vimserice.dll 라이브러리에 대한 참조를 추가 할 수 있습니다.

  8. 응용 프로그램을 실행하고 vimservice 객체 인스턴션 시간이 줄어드는지 확인하십시오.

추가 메모

SGEN 도구는 약간의 블랙 박스이며 동작은 Machine.Config 파일에있는 것에 따라 다릅니다. 예를 들어, 기본적으로 최적화되지 않은 비 곤경 코드를 ouptut해야하지만 항상 그런 것은 아닙니다. 도구에 약간의 가시성을 얻으려면 3 단계에서 /k 플래그를 사용하면 소스 파일 및 명령 줄 옵션 파일을 포함하여 모든 임시 생성 파일을 유지하게됩니다.

위의 수정 후에도 Vimservice 클래스를 처음으로 인스턴스화하는 데 걸리는 시간은 순간적이지 않습니다 (1.5 초). 경험적 관찰에 기초하여, 남은 시간의 대부분은 처리 때문인 것으로 보인다. SoapDocumentMethodAttribute 속성. 이 시점 에서이 시간이 어떻게 줄어들 수 있는지는 불분명합니다. 사전 생성 XMLSerializer 어셈블리는 SOAP 관련 속성을 설명하지 않으므로 이러한 속성은 코드에 남아 있어야합니다. 좋은 소식은 해당 앱에 대한 vimservice 클래스의 첫 번째 인스턴스화 만 오래 걸린다는 것입니다. 따라서 추가 1.5 초가 문제라면 로그인 시간의 사용자 경험을 향상시키기위한 수단으로 응용 프로그램의 시작 부분 에서이 클래스의 더미 인스턴스화를 시도 할 수 있습니다.

다른 팁

당신은 조사하고 싶을 수도 있습니다 Sgen.exe .NET과 함께 제공되는 도구. Visual Studio의 C# Project Properties "Build"페이지에는 자동으로 실행되는 "Build Serialization Assembly"라는 편리한 작은 것도 있습니다. Sgen 당신을 위한.

나는 이것이 Sgen 문제가 아니라고 생각합니다. 나는 생성자 코드를 살펴 보았고, 그것이 수업의 xmlincludeattribute를 기반으로하는 많은 반영을하고 있음을 알 수 있습니다. 그것은 그들 모두를 반영하고 정말로 오랜 시간이 걸릴 수 있습니다.

CRM과 함께 제공되는 사전 생성 XMLSerializer 어셈블리가 있습니다. GAC에 sdktypeproxy.xmlserializers.dll 및 sdkproxy.xmlserializers.dll이 있는지 확인하십시오.

그렇지 않은 경우 CRMSERVICE를 만들 때 .NET은 시간이 걸릴 수있는 XMLSerializer 어셈블리를 생성한다는 것을 의미합니다. 도움이 되었기를 바랍니다

나는 내 이니셜을 알아 내려고 할 때이 스레드를 발견했다 SoapHttpClientProtocol 전화가 너무 오래 걸렸습니다.

프록시를 NULL/빈으로 설정하는 것을 발견했습니다. 프록시 자동 측정이 발생하지 않도록 중지했습니다. 초기 호출에서 최대 7 초가 걸렸습니다.

this.Proxy = GlobalProxySelection.GetEmptyWebProxy();

위의 자세한 답변을 가이드로 사용했으며 몇 걸음 앞으로 나아 갔으며 프로세스를 자동화하기위한 스크립트를 만들었습니다. 스크립트는 두 파일로 만들어집니다.

GenerateProxy.bat :

REM if your path for wsdl, csc or sgen is missing, please add it here (it varies from machine to machine)
set PATH=%PATH%;C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6.1 Tools;C:\Program Files (x86)\MSBuild\14.0\Bin

wsdl http://localhost:57237/VIM_WS.asmx?wsdl REM create source code out of WSDL
PowerShell.exe -ExecutionPolicy Bypass -Command "& '%~dpn0.ps1'" REM proces source code (remove annotations, add other annotation, put class into namespace)
csc /t:library /out:references\VIM_Service.dll VIM_WS.cs REM compile source into dll
sgen /p references\VIM_Service.dll /force REM generate serializtion dll

GenerateProxy.ps1

(Get-Content VIM.cs) | 
    ForEach-Object { 
        $_ -replace "(?<attr>\[global::System.Xml.Serialization.[^\]]*\])", "/*${attr}*/" `
            -replace "public partial class VIM", "[System.Xml.Serialization.XmlSerializerAssemblyAttribute(AssemblyName = ""VIM_Service.XmlSerializers"")] `npublic partial class VIM" `
            -replace "using System;", "namespace Classes.WS_VIM {   `n`nusing System;"
    } |
Set-Content VIM.cs
Add-Content VIM.cs "`n}"

이 두 파일을 클라이언트 프로젝트에 추가했으며 건축 사전 이벤트에서 라인을 추가했습니다.

cd..\..
generateproxy

따라서 모든 빌드 전에 프록시 클래스가 재생되며 개발자는 거의 생각할 필요가 없습니다. 빌딩하는 동안 WS는 UP 및 실행 중이며 URL은 BAT 파일에 있어야합니다. Prebuild의 결과로 두 개의 DLL 파일이 클라이언트 프로젝트의 하위 폴더에서 재생됩니다. 참조. 스크립트를 처음 실행 한 후 새 DLL에 대한 참조를 추가해야합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top