Frage

Ich mache einige Experimente mit Microsoft Dynamics CRM. Sie interagieren mit ihm durch Web-Service und ich habe eine Web-Referenz zu meinem Projekt hinzugefügt. Die Web-Service-Schnittstelle ist sehr reich, und die erzeugte „Reference.cs“ ist einige 90k loc.

Ich bin mit der Web-Referenz in einer Konsolenanwendung. Ich wechsle oft etwas, neu kompilieren und ausführen. Compilation ist schnell, aber newing Die Web-Service-Referenz ist sehr langsam, einig 15-20 Sekunden unter: CrmService service = new CrmService(); Profilieren zeigt, dass alle Zeit in dem Soaphttpclientprotocol-Konstruktor ausgegeben wird.

Der Täter ist offenbar die Tatsache, dass der XML-Serialisierung-Code (nicht in den oben genannten 90k loc enthielt) zur Laufzeit erzeugt wird, bevor JIT'ed zu sein. Dies geschieht während des Konstruktoraufruf. Das Warten ist ziemlich frustrierend, wenn herum spielen und versuchen, die Dinge aus.

Ich habe verschiedene Kombinationen von sgen.exe, ngen und XGenPlus versucht (die mehrere Stunden dauert und erzeugt 500 MB zusätzlichen Code), aber ohne Erfolg. Ich habe einen Windows-Dienst mit der Umsetzung, die nur wenige CrmService Instanzen bereit haben auszuteilen, wenn nötig, aber das scheint übertrieben.

Irgendwelche Ideen?

War es hilfreich?

Lösung

Die folgenden von dieser Thread ist auf der VMWare-Foren zerrissen wird:

Hallo Leute,

Wir haben festgestellt, dass sgen.exe funktioniert. It'just, dass es ein paar zusätzliche Schritte über Pre-Erzeugung der Serializer DLL, die wir in diesem Thread verpasst. Hier ist die ausführliche Anleitung

PROBLEM

Wenn der VIM 2.0 SDK von .NET erfordert lange Zeit, um die VimService Klasse zu instanziiert. (Die VimService Klasse ist die Proxy-Klasse erzeugt, indem Sie 'wsdl.exe vim.wsdl vimService.wsdl')

Mit anderen Worten, die folgende Codezeile:

_service = new VimService();

Könnte etwa 50 Sekunden auszuführen nehmen.

Ursache

Offensichtlich nutzt die .NET XmlSerializer die System.Xml.Serialization.* Attribute, um die Proxy-Klassen mit Anmerkungen versehen Serialisierungscode in der Laufzeit zu erzeugen. Wenn die Proxy-Klassen viele und groß sind, wie der Code in VimService.cs ist, kann die Erzeugung des Serialisierungscode eine lange Zeit in Anspruch nehmen.

SOLUTION

Dies ist ein bekanntes Problem mit, wie der Microsoft .NET-Serializer funktioniert.

Hier sind einige Hinweise, dass MSDN bietet dieses Problem zu lösen:

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

Leider ist keines der oben genannten Referenzen beschreibt die komplette Lösung für das Problem. Stattdessen konzentrieren sie sich auf, wie die XML-Serialisierung Code vorab zu erzeugen.

Das komplette Update umfasst die folgenden Schritte:

  1. Erstellen Sie eine Assembly (DLL) mit der vorab generierten XML Serializer Code

  2. Entfernen Sie alle Verweise auf System.Xml.Serialization. * Attribute aus dem Proxy-Code (das heißt von der VimService.cs Datei)

  3. Beschriften des Haupt Proxy-Klasse mit dem XmlSerializerAssemblyAttribute es zu zeigen, wo der XML-Serializer Montag ist.

Auslassen von Schritt 2 führt zu nur 20% Verbesserung der Instanziierung Zeit für die VimService Klasse. Auslassen von entweder Schritt 1 oder 3 führt zu falschem Code. Bei allen drei Schritten 98% Verbesserung erreicht.

Hier ist Schritt-für-Schritt-Anleitung:

Bevor Sie beginnen, stellt sicher, dass Sie .NET verison 2.0-Tools verwenden. Diese Lösung wird nicht mit der Version 1.1 von .NET arbeiten, weil das sgen Werkzeug und die XmlSerializationAssemblyAttribute sind nur in der Version 2.0 von .NET

  1. Generieren Sie die VimService.cs Datei aus dem WSDL, mit wsdl.exe:

    wsdl.exe vim.wsdl vimService.wsdl

    Dies wird gibt die VimService.cs im aktuellen Verzeichnis-Datei

  2. Übersetzen VimService.cs in eine Bibliothek

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

  3. Mit dem sgen Werkzeug, um die XML-Serializer vorab generieren und kompilieren:

    sgen /p VimService.dll

    Dies wird Ausgang der VimService.XmlSerializers.dll im aktuellen Verzeichnis

  4. zum VimService.cs Datei Gehen Sie zurück und entfernen Sie alle System.Xml.Serialization.* Attribute. Da der Code-Code ist groß, der beste Weg, das zu erreichen, ist durch einige reguläre Ausdrücke Substitution Werkzeug. Seien Sie vorsichtig, wie Sie dies tun, weil nicht alle Attribute auf einer eigenen Zeile erscheinen. Einige sind in ausgekleideten im Rahmen einer Methodendeklaration.

    Wenn Sie diesen Schritt schwierig finden, hier ist eine vereinfachte Art und Weise tun:

    Angenommen, Sie C # schreiben, tun ein global auf die folgende Zeichenfolge ersetzen:

    [System.Xml.Serialization.XmlIncludeAttribute

    und ersetzen Sie es mit:

    // [System.Xml.Serialization.XmlIncludeAttribute

    Dies wird loszuwerden, die Xml.Serialization Attribute erhalten, die die größten Übeltäter für die Verlangsamung sind von ihnen aus zu kommentieren. Wenn Sie eine andere .NET-Sprache verwenden, ändern Sie nur the ersetzte Zeichenkette entsprechend dieser Sprache auf die Syntax-Präfix-kommentiert werden. Dieser vereinfachte Ansatz finden Sie die meisten der Speedup bekommen, die Sie bekommen können. Entfernen Sie den Rest des Xml.Serialization Attribute erreicht nur eine zusätzliche 0,2 sec Speedup.

  5. Fügen Sie das folgende Attribut zum VimService Klasse in VimService.cs:

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

    Sie sollten mit etwas am Ende wie folgt:

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

  6. Regenerieren VimSerice.dll Bibliothek von

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

  7. Nun, aus Ihrer Anwendung, können Sie einen Verweis auf VimSerice.dll Bibliothek hinzufügen können.

  8. Ihre Anwendung ausführen und dass VimService Objekt Instanciation Zeit überprüfen verringert wird.

Sonstige Erläuterungen

Das sgen Tool ist ein bisschen eine Blackbox und sein Verhalten ändert sich je nachdem, was Sie in Ihrer Datei Machine.config haben. Zum Beispiel wird es standardmäßig soll optimiert nicht-Debug-Code ouptut, aber das ist nicht immer der Fall. Um eine gewisse Sichtbarkeit in das Werkzeug zu bekommen, verwenden Sie die / k-Flag in Schritt 3, was es bewirkt, dass alle seine temporären erzeugten Dateien zu halten, einschließlich der Quelldateien und Befehlszeilenoption Dateien, die es erzeugt.

Auch nach der oben fixiert die Zeit, die die VimService Klasse zum ersten Mal zu instanziiert nimmt, ist nicht sofort (1,5 sec). Basierend auf empirischen Beobachtungen scheint es, dass die Mehrheit der verbleibenden Zeit zum Verarbeiten der SoapDocumentMethodAttribute Attribute beruht. An dieser Stelle ist es unklar, wie diese Zeit reduziert werden kann. Die vorab generierte XmlSerializer Montage berücksichtigt nicht die SOAP-bezogenen Attribute, so müssen diese Attribute im Code bleiben. Die gute Nachricht ist, dass nur die erste Instanziierung der VimService Klasse für diese App lange dauert. Also, wenn die zusätzlichen 1,5 Sekunden sind ein Problem, könnte man versuchen, eine Dummy-Instanziierung dieser Klasse zu Beginn der Anwendung als Mittel zu tun, User Experience von Login-Zeit zu verbessern.

Andere Tipps

Ich glaube, dass dies keine SGEN Problem. Ich habe an dem Konstruktor Code sah, und ich sehe, dass es eine Menge Reflexion tut (basierend auf dem XmlIncludeAttribute auf der Klasse). Es spiegelt auf alle von ihnen und kann eine wirklich lange Zeit in Anspruch nehmen.

Es gibt einen vorab generierte XmlSerializer Assembly, die mit CRM kommt. Überprüfen Sie, ob Sie SdkTypeProxy.XmlSerializers.dll und SdkProxy.XmlSerializers.dll im GAC.

Wenn Sie nicht dann tun, das bedeutet, dass, wenn Sie die CrmService erstellen, .net die XmlSerializer Baugruppe erzeugen, die eine gewisse Zeit in Anspruch nehmen kann. Hoffe, das hilft

Ich kam diesen Thread über, wenn meine erste SoapHttpClientProtocol Anrufe finden versuchen, herauszufinden, warum wurden so lange dauern würde.

Ich fand, dass die Proxy-Einstellung auf null / gestoppt Leeren Sie den Proxy AutoDetect auftreten - Dies wurde auf 7 Sekunden auf dem ersten Aufruf Aufnahme:

this.Proxy = GlobalProxySelection.GetEmptyWebProxy();

Ich habe oben ausführliche Antwort als Leitfaden verwendet, und ging ein paar Schritte vorwärts, ein Skript zu machen Prozess zu automatisieren. Script wird aus zwei Dateien:

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}"

Ich habe diese beiden Dateien auf Client-Projekt, und in dem Pre-Build-Ereignisse hinzugefügt habe ich hinzugefügt Zeilen

cd..\..
generateproxy

Also, vor jedem Build, sind Proxy-Klassen regenerieren und Entwickler hat (fast) keine Notwendigkeit, darüber nachzudenken. Beim Bau muss WS eingerichtet sein und ausgeführt, und die entsprechende URL in Bat-Datei sein muss. Als Folge des vorkompilierte, zwei DLL-Dateien im Client-Projekt Unterordner regenerieren Referenzen . Nach dem ersten Ausführung von Skripten, sollten Sie Bezug auf neue DLL hinzuzufügen.

scroll top