以下は、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 シリアル化コードを事前に生成する方法に焦点を当てています。
完全な修正には、次の手順が含まれます。
事前に生成された XML シリアライザー コードを使用してアセンブリ (DLL) を作成する
System.Xml.Serialization.* 属性へのすべての参照をプロキシ コードから (つまり、VimService.cs ファイルから) 削除します。
XmlSerializerAssemblyAttribute を使用してメイン プロキシ クラスに注釈を付け、XML シリアライザー アセンブリの場所を指すようにします。
ステップ 2 をスキップしても、VimService
クラスのインスタンス化時間は 20% しか改善されません。ステップ 1 または 3 のいずれかをスキップすると、コードが正しくなくなります。3 つのステップすべてで、98% の改善が達成されます。
段階的な手順は次のとおりです。
開始する前に、.NET バージョン 2.0 ツールを使用していることを確認してください。このソリューションは、.NET のバージョン 1.1 では機能しません。これは、sgen ツールとXmlSerializationAssemblyAttribute
が .NET のバージョン 2.0 でのみ使用できるためです。
wsdl.exe を使用して、WSDL から VimService.cs ファイルを生成します。
wsdl.exe vim.wsdl vimService.wsdl
これにより、現在のディレクトリに VimService.cs ファイルが出力されます。
VimService.cs をライブラリにコンパイルする
csc /t:library /out:VimService.dll VimService.cs
sgen ツールを使用して、XML シリアライザーを事前に生成およびコンパイルします。
sgen /p VimService.dll
これにより、現在のディレクトリに VimService.XmlSerializers.dll が出力されます
VimService.cs ファイルに戻り、すべてのSystem.Xml.Serialization.*
属性を削除します。コード コードは大きいため、これを実現する最善の方法は、正規表現置換ツールを使用することです。すべての属性が単独で 1 行に表示されるわけではないため、これを行うときは注意してください。メソッド宣言の一部としてインライン化されているものもあります。
このステップが難しい場合は、次の簡単な方法を使用してください。
C# を書いていると仮定すると、次の文字列に対してグローバル置換を実行します。
[System.Xml.Serialization.XmlIncludeAttribute
そしてそれを次のように置き換えます:
// [System.Xml.Serialization.XmlIncludeAttribute
Xml.Serialization
これにより、減速の最大の原因である属性をコメントアウトすることで取り除くことができます。他の .NET 言語を使用している場合は、その言語の構文に従って、置換された文字列をプレフィックス コメントに変更するだけです。この単純化されたアプローチにより、得られるスピードアップのほとんどが得られます。残りの Xml.Serialization 属性を削除しても、さらに 0.2 秒高速化されるだけです。
次の属性を 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
VimSerice.dll ライブラリを再生成します。
csc /t:library /out:VimService.dll VimService.cs
これで、アプリケーションから VimSerice.dll ライブラリへの参照を追加できます。
アプリケーションを実行し、VimService オブジェクトのインスタンス化時間が短縮されていることを確認します。
その他の注意事項
sgen ツールは少しブラック ボックスであり、その動作は Machine.config ファイルの内容によって異なります。たとえば、デフォルトでは、最適化された非デバッグ コードを出力することになっていますが、常にそうであるとは限りません。ツールをある程度可視化するには、ステップ 3 で /k フラグを使用します。これにより、生成されたソース ファイルやコマンド ライン オプション ファイルを含む、一時的に生成されたすべてのファイルが保持されます。
上記の修正後でも、VimService クラスを初めてインスタンス化するのにかかる時間は瞬時ではありません (1.5 秒)。経験的な観察に基づくと、残り時間の大部分はSoapDocumentMethodAttribute
属性の処理に費やされているようです。現時点では、この時間を短縮する方法は不明です。事前に生成された XmlSerializer アセンブリは SOAP 関連の属性を考慮していないため、これらの属性はコードに残す必要があります。幸いなことに、そのアプリの VimService クラスの最初のインスタンス化だけに時間がかかります。したがって、余分な 1.5 秒が問題になる場合は、ログイン時間のユーザー エクスペリエンスを改善する手段として、アプリケーションの開始時にこのクラスのダミー インスタンス化を試みることができます。