以下内容摘自this http://communities.vmware.com/thread/47063VMWare 论坛上的帖子:
嗨伙计,
我们发现 sgen.exe 确实有效。只是除了预生成序列化器 dll 之外,我们在本线程中还漏掉了一些额外的步骤。这是详细说明
PROBLEM
当使用 .NET 中的 VIM 2.0 SDK 时,需要很长时间来实例化 VimService 类。 (VimService类是运行'wsdl.exe vim.wsdl vimService.wsdl'生成的代理类)
换句话说,下面这行代码:
_service = new VimService();
执行可能需要大约 50 秒。
CAUSE
显然,.NETXmlSerializer
使用System.Xml.Serialization.*
注释代理类的属性以在运行时生成序列化代码。当代理类又多又大时,就像 VimService.cs 中的代码一样,序列化代码的生成可能需要很长时间。
SOLUTION
这是 Microsoft .NET 序列化程序工作方式的一个已知问题。
以下是 MSDN 提供的一些有关解决此问题的参考资料:
http://msdn2.microsoft.com/en-us/library/bk3w6240.aspx http://msdn2.microsoft.com/en-us/library/bk3w6240.aspx
http://msdn2.microsoft.com/en-us/library/system.xml.serialization.xmlserializer assemblyattribute.aspx http://msdn2.microsoft.com/en-us/library/system.xml.serialization.xmlserializerassemblyattribute.aspx
不幸的是,上述参考文献都没有描述该问题的完整解决方案。相反,他们关注如何预先生成 XML 序列化代码。
完整的修复涉及以下步骤:
使用预先生成的 XML 序列化程序代码创建程序集(DLL)
从代理代码(即从 VimService.cs 文件)中删除对 System.Xml.Serialization.* 属性的所有引用
使用 XmlSerializerAssemblyAttribute 注释主代理类,以将其指向 XML 序列化程序集所在的位置。
跳过第 2 步只会导致实例化时间缩短 20%VimService
班级。跳过步骤 1 或 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.*
属性。由于代码量较大,实现这一点的最佳方法是使用一些正则表达式替换工具。执行此操作时要小心,因为并非所有属性都单独出现在一行上。有些是作为方法声明的一部分内联的。
如果您发现这一步很困难,这里有一个简化的方法:
假设您正在编写 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 秒是一个问题,可以尝试在应用程序开始时对此类进行虚拟实例化,作为改善用户登录时间体验的一种方法。