首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >慢速SoapHttpClientProtocol构造函数

慢速SoapHttpClientProtocol构造函数
EN

Stack Overflow用户
提问于 2008-10-05 14:52:53
回答 6查看 12.7K关注 0票数 30

我正在使用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实例可以在需要的时候分发,但这似乎有点过了。

有什么想法吗?

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2009-06-08 16:48:37

以下内容摘自VMWare论坛上的this帖子:

大家好,

我们发现sgen.exe确实可以工作。只是除了我们在这个线程中遗漏的预生成序列化程序dll之外,还有一些额外的步骤。以下是详细说明

问题

在使用vim2.0SDK时,.NET需要很长时间来实例化VimService类。( VimService类是通过运行'wsdl.exe vim.wsdl vimService.wsdl‘生成的代理类)

换句话说,下面这行代码:

代码语言:javascript
复制
_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序列化代码。

完整的修复包括以下步骤:

  1. 使用预先生成的XML序列化程序代码创建程序集( DLL)
  2. 从代理代码中删除对System.Xml.Serialization.*属性的所有引用(例如,从VimService.cs代理类中),并使用XmlSerializerAssemblyAttribute将其指向XML序列化程序程序集所在的位置。

跳过步骤2只会使VimService类的实例化时间缩短20%。跳过步骤1或步骤3都会导致错误的代码。通过这三个步骤,实现了98%的改进。

以下是分步说明:

开始之前,请确保您使用的是.NET verison 2.0工具。此解决方案不适用于.NET 1.1版,因为sgen工具和XmlSerializationAssemblyAttribute仅在2.0版的.NET中可用

  1. 使用wsdl.exe从WSDL生成VimService.cs文件:

wsdl.exe vim.wsdl vimService.wsdl

这会将当前directory

  • Compile VimService.cs中的VimService.cs文件输出到库中

使用sgen工具预先生成和编译csc /t:library /out:VimService.dll VimService.cs

  • Use序列化程序:

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

  • Regenerate VimSerice.dll库,由

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

  • Now,从您的应用程序中,您可以添加对VimSerice.dll库的引用。

  • 运行您的应用程序并验证VimService对象实例化时间是否缩短。

补充说明

sgen工具有点像黑盒,它的行为根据Machine.config文件中的内容而有所不同。例如,默认情况下,它会输出优化的非调试代码,但情况并不总是这样。要了解该工具,请在步骤3中使用/k标志,这将使它保留所有临时生成的文件,包括它生成的源文件和命令行选项文件。

即使在上述修复之后,第一次实例化VimService类所需的时间也不是即时的(1.5秒)。根据经验观察,大部分剩余时间似乎是由于处理SoapDocumentMethodAttribute属性造成的。在这一点上,还不清楚如何减少这一时间。预先生成的XmlSerializer程序集不考虑与SOAP相关的属性,因此这些属性需要保留在代码中。好消息是,仅该应用程序的VimService类的第一个实例化就需要很长时间。因此,如果额外的1.5秒是一个问题,可以尝试在应用程序开始时执行此类的虚拟实例化,以此作为改善登录时间的用户体验的一种手段。

票数 38
EN

Stack Overflow用户

发布于 2008-10-05 15:03:16

你可能想看看.NET附带的Sgen.exe工具,在Visual Studio的C#项目属性"Build“页面的最底部有一个很方便的小东西,叫做"Build serialization assembly”,它会自动为你运行Sgen

票数 1
EN

Stack Overflow用户

发布于 2008-11-18 04:51:52

我相信这不是SGEN的问题。我看过构造函数代码,我看到它做了很多反射(基于类上的XmlIncludeAttribute )。它反映了所有这些问题,并且可能需要很长时间。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/172095

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档