我正在使用Microsoft Dynamics CRM进行一些实验。您可以通过web服务与它交互,并且我已经在我的项目中添加了一个Web引用。web服务接口非常丰富,生成的"Reference.cs“大约是90k loc。
我在一个控制台应用程序中使用web引用。我经常修改一些东西,重新编译和运行。编译很快,但是更新web服务引用非常慢,大约需要15-20秒:CrmService service = new CrmService();分析显示所有时间都花在SoapHttpClientProtocol构造函数上。
罪魁祸首显然是XML序列化代码(不包括在上面提到的90kloc中)是在运行时生成的,然后才被JIT‘’ed。这在构造函数调用期间发生。等待是相当令人沮丧的,当玩和尝试的东西。
我尝试了sgen.exe、ngen和XGenPlus的各种组合(这需要几个小时并生成500MB的额外代码),但都没有用。我曾经考虑过实现一个Windows服务,它只有很少的CrmService实例可以在需要的时候分发,但这似乎有点过了。
有什么想法吗?
发布于 2009-06-08 16:48:37
以下内容摘自VMWare论坛上的this帖子:
大家好,
我们发现sgen.exe确实可以工作。只是除了我们在这个线程中遗漏的预生成序列化程序dll之外,还有一些额外的步骤。以下是详细说明
问题
在使用vim2.0SDK时,.NET需要很长时间来实例化VimService类。( VimService类是通过运行'wsdl.exe vim.wsdl vimService.wsdl‘生成的代理类)
换句话说,下面这行代码:
_service = new VimService();可能需要大约50秒才能执行。
原因
显然,.NET XmlSerializer使用注释代理类的System.Xml.Serialization.*属性在运行时生成序列化代码。当代理类很多且很大时,就像VimService.cs中的代码一样,序列化代码的生成可能需要很长时间。
解决方案
这是一个关于微软.NET序列化程序工作方式的已知问题。
以下是MSDN提供的有关解决此问题的一些参考:
http://msdn2.microsoft.com/en-us/library/bk3w6240.aspx http://msdn2.microsoft.com/en-us/library/system.xml.serialization.xmlserializerassemblyattribute.aspx
不幸的是,上面的参考文献都没有描述这个问题的完整解决方案。相反,他们关注的是如何预先生成XML序列化代码。
完整的修复包括以下步骤:
跳过步骤2只会使VimService类的实例化时间缩短20%。跳过步骤1或步骤3都会导致错误的代码。通过这三个步骤,实现了98%的改进。
以下是分步说明:
开始之前,请确保您使用的是.NET verison 2.0工具。此解决方案不适用于.NET 1.1版,因为sgen工具和XmlSerializationAssemblyAttribute仅在2.0版的.NET中可用
wsdl.exe vim.wsdl vimService.wsdl
这会将当前directory
使用sgen工具预先生成和编译csc /t:library /out:VimService.dll VimService.cs
sgen /p VimService.dll
这将输出当前目录
System.Xml.Serialization.*属性。因为代码很大,所以最好的方法是使用一些正则表达式替换工具。执行此操作时要小心,因为并非所有属性都会单独出现在一行中。有些是内联的,作为方法声明的一部分。如果你觉得这一步很难,这里有一个简化的方法:
假设您正在编写C#,请对以下字符串执行全局替换:
[System.Xml.Serialization.XmlIncludeAttribute
并将其替换为:
// [System.Xml.Serialization.XmlIncludeAttribute
这将通过注释掉Xml.Serialization属性来消除它们,这些属性是导致速度减慢的最大原因。如果您正在使用其他.NET语言,只需根据该语言的语法将替换的字符串修改为前缀注释即可。这种简化的方法将使您获得最大程度的加速。删除其余的Xml.Serialization属性只能额外获得0.2秒的加速。
[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
csc /t:library /out:VimService.dll VimService.cs
补充说明
sgen工具有点像黑盒,它的行为根据Machine.config文件中的内容而有所不同。例如,默认情况下,它会输出优化的非调试代码,但情况并不总是这样。要了解该工具,请在步骤3中使用/k标志,这将使它保留所有临时生成的文件,包括它生成的源文件和命令行选项文件。
即使在上述修复之后,第一次实例化VimService类所需的时间也不是即时的(1.5秒)。根据经验观察,大部分剩余时间似乎是由于处理SoapDocumentMethodAttribute属性造成的。在这一点上,还不清楚如何减少这一时间。预先生成的XmlSerializer程序集不考虑与SOAP相关的属性,因此这些属性需要保留在代码中。好消息是,仅该应用程序的VimService类的第一个实例化就需要很长时间。因此,如果额外的1.5秒是一个问题,可以尝试在应用程序开始时执行此类的虚拟实例化,以此作为改善登录时间的用户体验的一种手段。
发布于 2008-10-05 15:03:16
你可能想看看.NET附带的Sgen.exe工具,在Visual Studio的C#项目属性"Build“页面的最底部有一个很方便的小东西,叫做"Build serialization assembly”,它会自动为你运行Sgen。
发布于 2008-11-18 04:51:52
我相信这不是SGEN的问题。我看过构造函数代码,我看到它做了很多反射(基于类上的XmlIncludeAttribute )。它反映了所有这些问题,并且可能需要很长时间。
https://stackoverflow.com/questions/172095
复制相似问题