30

Microsoft Dynamics CRM を使っていくつかの実験を行っています。Web サービスを介して対話し、プロジェクトに Web 参照を追加しました。Web サービス インターフェイスは非常に豊富で、生成された "Reference.cs" は 90k loc です。

コンソール アプリケーションで Web リファレンスを使用しています。私はしばしば何かを変更し、再コンパイルして実行します。コンパイルは高速ですが、Web サービス参照の更新は非常に遅く、15 ~ 20 秒かかります。 CrmService service = new CrmService(); プロファイリングにより、すべての時間が SoapHttpClientProtocol コンストラクターで費やされていることがわかります。

原因は明らかに、XML シリアライゼーション コード (上記の 90k loc には含まれていません) が、JIT される前に実行時に生成されるという事実です。これは、コンストラクターの呼び出し中に発生します。遊んで試してみると、待ち時間はかなりイライラします。

sgen.exe、ngen、および XGenPlus (数時間かかり、500MB の追加コードが生成される) のさまざまな組み合わせを試しましたが、役に立ちませんでした。私は、必要に応じて準備ができている CrmService インスタンスがほとんどない Windows サービスを実装することを検討しましたが、それは過剰に思えます。

何か案は?

4

6 に答える 6

38

以下は、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 シリアライザー コードを使用してアセンブリ (DLL) を作成する

  2. System.Xml.Serialization.* 属性へのすべての参照をプロキシ コードから (つまり、VimService.cs ファイルから) 削除します。

  3. XmlSerializerAssemblyAttribute を使用してメイン プロキシ クラスに注釈を付け、XML シリアライザー アセンブリの場所を指すようにします。

ステップ 2 をスキップしても、VimServiceクラスのインスタンス化時間は 20% しか改善されません。ステップ 1 または 3 のいずれかをスキップすると、コードが正しくなくなります。3 つのステップすべてで、98% の改善が達成されます。

段階的な手順は次のとおりです。

開始する前に、.NET バージョン 2.0 ツールを使用していることを確認してください。このソリューションは、.NET のバージョン 1.1 では機能しません。これは、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.*属性を削除します。コード コードは大きいため、これを実現する最善の方法は、正規表現置換ツールを使用することです。すべての属性が単独で 1 行に表示されるわけではないため、これを行うときは注意してください。メソッド宣言の一部としてインライン化されているものもあります。

    このステップが難しい場合は、次の簡単な方法を使用してください。

    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 ファイルの内容によって異なります。たとえば、デフォルトでは、最適化された非デバッグ コードを出力することになっていますが、常にそうであるとは限りません。ツールをある程度可視化するには、ステップ 3 で /k フラグを使用します。これにより、生成されたソース ファイルやコマンド ライン オプション ファイルを含む、一時的に生成されたすべてのファイルが保持されます。

上記の修正後でも、VimService クラスを初めてインスタンス化するのにかかる時間は瞬時ではありません (1.5 秒)。経験的な観察に基づくと、残り時間の大部分はSoapDocumentMethodAttribute属性の処理に費やされているようです。現時点では、この時間を短縮する方法は不明です。事前に生成された XmlSerializer アセンブリは SOAP 関連の属性を考慮していないため、これらの属性はコードに残す必要があります。幸いなことに、そのアプリの VimService クラスの最初のインスタンス化だけに時間がかかります。したがって、余分な 1.5 秒が問題になる場合は、ログイン時間のユーザー エクスペリエンスを改善する手段として、アプリケーションの開始時にこのクラスのダミー インスタンス化を試みることができます。

于 2009-06-08T16:48:37.450 に答える
1

CRMに付属する事前生成されたXmlSerializerアセンブリがあります。GACにSdkTypeProxy.XmlSerializers.dllとSdkProxy.XmlSerializers.dllがあるかどうかを確認します。

そうでない場合は、CrmServiceを作成するときに、.netがXmlSerializerアセンブリを生成することを意味します。これには時間がかかる場合があります。お役に立てれば

于 2008-12-17T22:07:12.487 に答える
1

これは SGEN の問題ではないと思います。コンストラクター コードを調べたところ、(クラスの XmlIncludeAttribute に基づいて) 多くのリフレクションが行われていることがわかりました。それらすべてに反映され、非常に長い時間がかかる場合があります。

于 2008-11-18T04:51:52.027 に答える
1

Sgen.exe.NET に付属のツールを調べることをお勧めします。Visual Studio の C# プロジェクト プロパティの [ビルド] ページの一番下には、自動的に実行される [シリアル化アセンブリのビルド] という便利な機能もありSgenます。

于 2008-10-05T15:03:16.180 に答える
0

SoapHttpClientProtocol最初の通話に時間がかかる理由を調べようとしたときに、このスレッドに出くわしました。

Proxy を null/Empty に設定すると、Proxy AutoDetect が停止することがわかりました。これには、最初の呼び出しで最大 7 秒かかっていました。

this.Proxy = GlobalProxySelection.GetEmptyWebProxy();
于 2012-12-07T01:13:50.747 に答える