慢SoapHttpClientProtocol构造SoapHttpClientProtocol

2023-09-02 21:10:18 作者:詠bù琂敗οΟ

我在做与Microsoft Dynamics CRM的一些实验。您可以通过Web服务与它互动,我添加了一个Web引用到我的项目。 Web服务接口非常丰富,而且生成的Reference.cs是一些90K禄。

I'm doing some experiments with Microsoft Dynamics CRM. You interact with it through web services and I have added a Web Reference to my project. The web service interface is very rich, and the generated "Reference.cs" is some 90k loc.

我使用一个控制台应用程序的Web引用。我经常改变的东西,重新编译和运行。编译速度很快,但是newing了Web服务的引用很慢,服用一些15-20秒:     CrmService服务=新CrmService(); 性能分析表明,所有的时间都用在SoapHttpClientProtocol构造。

I'm using the web reference in a console application. I often change something, recompile and run. Compilation is fast, but newing up the web service reference is very slow, taking some 15-20 seconds: CrmService service = new CrmService(); Profiling reveals that all time is spent in the SoapHttpClientProtocol constructor.

罪魁祸首是显然的XML序列化code(不包括在上述90K LOC)在运行时产生的,是JIT'ed前的事实。这发生在构造函数调用中。玩弄和尝试的东西出来时,等待是相当令人沮丧的。

The culprit is apparently the fact that the XML serialization code (not included in the 90k loc mentioned above) is generated at run time, before being JIT'ed. This happens during the constructor call. The wait is rather frustrating when playing around and trying things out.

我已经试过了sgen.exe,NGEN和XGenPlus(这需要几个小时,并产生额外的code 500MB),但无济于事各种组合。我已经考虑推行的Windows服务,很少有CrmService情况下,准备在需要时抛出,但似乎过大。

I've tried various combinations of sgen.exe, ngen and XGenPlus (which takes several hours and generates 500MB of additional code) but to no avail. I've considered implementing a Windows service that have few CrmService instances ready to dish out when needed but that seems excessive.

任何想法?

推荐答案

以下是从在这个线程撕开VMWare的论坛:

The following is ripped from this thread on the VMWare forums:

乡亲

我们已经发现,sgen.exe做的工作。 It'just有几个超过pre-产生,我们错过了这个线程串行DLL的额外步骤。下面是详细说明

We've found that sgen.exe does work. It'just that there is a couple of additional steps beyond pre-generating the serializer dll's that we missed in this thread. Here is the detailed instruction

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

When using the VIM 2.0 SDK from .NET requires long time to instantiate the VimService class. (The VimService class is the proxy class generated by running 'wsdl.exe vim.wsdl vimService.wsdl')

在换句话说,code以下行:

In other words, the following line of code:

_service = new VimService();

可能需要50秒左右来执行。

Could take about 50 seconds to execute.

显然,.NET 的XmlSerializer 使用的System.Xml.Serialization。* 属性标注的代理类生成序列code的运行时间。当代理类多而大,因为是code在VimService.cs,的序列化code的产生可能需要很长的时间。

Apparently, the .NET XmlSerializer uses the System.Xml.Serialization.* attributes annotating the proxy classes to generate serialization code in run time. When the proxy classes are many and large, as is the code in VimService.cs, the generation of the serialization code can take a long time.

这是一个已知的问题是如何在Microsoft .NET序列化的工作。

This is a known problem with how the Microsoft .NET serializer works.

下面是一些参考的MSDN提供了有关解决这个问题:

Here are some references that MSDN provides about solving this problem:

http://msdn2.microsoft.com/en-us/library/bk3w6240.aspx http://msdn2.microsoft.com/en-us/library/system.xml.serialization.xmlserializerassemblyattribute.aspx

不幸的是,没有一个上述参考文献中描述的完整的解决问题的办法。相反,他们把重点放在如何pre-生成XML序列化code。

Unfortunately, none of the above references describe the complete solution to the problem. Instead they focus on how to pre-generate the XML serialization code.

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

The complete fix involves the following steps:

创建一个程序集(一个DLL)与pre-生成的XML序列化code

Create an assembly (a DLL) with the pre-generated XML serializer code

删除来的System.Xml.Serialization所有引用。*从代理code属性(即从VimService.cs文件)

Remove all references to System.Xml.Serialization.* attributes from the proxy code (i.e. from the VimService.cs file)

注释主要代理类与XmlSerializerAssemblyAttribute把它指向哪里XML序列组装。

Annotate the main proxy class with the XmlSerializerAssemblyAttribute to point it to where the XML serializer assembly is.

跳过步骤2导致的实例时间 VimService 类只有20%的改善。跳过任一步骤1或3导致不正确code。与所有三个步骤98%的改善,实现

Skipping step 2 leads to only 20% improvement in the instantiation time for the VimService class. Skipping either step 1 or 3 leads to incorrect code. With all three steps 98% improvement is achieved.

下面是一步一步的说明:

Here are step-by-step instructions:

在开始之前,确保你使用的是.NET verison 2.0工具。该解决方案将不会与.NET 1.1版工作,因为SGEN工具和 XmlSerializationAssemblyAttribute 仅在.NET 2.0版本

Before you begin, makes sure you are using .NET verison 2.0 tools. This solution will not work with version 1.1 of .NET because the sgen tool and the XmlSerializationAssemblyAttribute are only available in version 2.0 of .NET

根据WSDL的VimService.cs文件,使用Wsdl.exe用:

Generate the VimService.cs file from the WSDL, using wsdl.exe:

Wsdl.exe用vim.wsdl vimService.wsdl

这将输出VimService.cs在当前目录下的文件

This will output the VimService.cs file in the current directory

编译VimService.cs到库

Compile VimService.cs into a library

CSC / T:库/out:VimService.dll VimService.cs

使用的SGEN工具pre-生成和编译XML序列化:

Use the sgen tool to pre-generate and compile the XML serializers:

SGEN / p VimService.dll

这将输出VimService.XmlSerializers.dll在当前目录

This will output the VimService.XmlSerializers.dll in the current directory

返回到VimService.cs文件,并删除所有的System.Xml.Serialization。* 属性。因为code code是大的,实现这一目标的最佳途径是使用一些正规EX pression替代工具。要小心,因为你这样做,因为不是所有的属性出现在一行由自己决定。有些是在内衬作为一个方法声明的部分。

Go back to the VimService.cs file and remove all System.Xml.Serialization.* attributes. Because the code code is large, the best way to achieve that is by using some regular expression substitution tool. Be careful as you do this because not all attributes appear on a line by themselves. Some are in-lined as part of a method declaration.

如果你发现这一步很难,这里是做了一个简单的方式:

If you find this step difficult, here is a simplified way of doing it:

假设你正在编写C#,做一个全球替换以下字符串:

Assuming you are writing C#, do a global replace on the following string:

[System.Xml.Serialization.XmlIncludeAttribute

和将其替换为:

// [System.Xml.Serialization.XmlIncludeAttribute

这将摆脱的 Xml.Serialization 属性是最大的罪魁祸首减速通过注释出来。如果你使用的是其他一些.NET语言,只需修改替换字符串为preFIX-评论根据该语言的语法。这种简化的方法将让你最,你可以得到的加速比。卸下Xml.Serialization其余属性只实现了一个额外的0.2秒加速。

This will get rid of the Xml.Serialization attributes that are the biggest culprits for the slowdown by commenting them out. If you are using some other .NET language, just modify the replaced string to be prefix-commented according to the syntax of that language. This simplified approach will get you most of the speedup that you can get. Removing the rest of the Xml.Serialization attributes only achieves an extra 0.2 sec speedup.

添加以下属性到VimService类VimService.cs:

Add the following attribute to the VimService class in VimService.cs:

[System.Xml.Serialization.XmlSerializerAssemblyAttribute(的AssemblyName =VimService.XmlSerializers)]

您应该结束了这样的事情:

You should end up with something like this:

// ...一些code在这里... [System.Xml.Serialization.XmlSerializerAssemblyAttribute(的AssemblyName =VimService.XmlSerializers)] 公共部分类VimService:System.Web.Services.Protocols.SoapHttpClientProtocol { // ...更多code此处

// ... Some code here ... [System.Xml.Serialization.XmlSerializerAssemblyAttribute(AssemblyName = "VimService.XmlSerializers")] public partial class VimService : System.Web.Services.Protocols.SoapHttpClientProtocol { // ... More code here

重新生成VimSerice.dll文库

Regenerate VimSerice.dll library by

CSC / T:库/out:VimService.dll VimService.cs

现在,从您的应用程序,你可以添加一个参考VimSerice.dll库。

Now, from your application, you can add a reference to VimSerice.dll library.

运行应用程序,并验证VimService对象instanciation时间减少了。

Run your application and verify that VimService object instanciation time is reduced.

查看sgen工具是一个黑盒,并取决于你在你的Machine.config文件的行为会有所不同。例如,在默认情况下它应该ouptut优化非调试code,但事实并非总是如此。为了得到一些可视化的工具,使用/ K标志在步骤3中,这将导致它让所有的临时生成的文件,包括它生成的源文件和命令行选项文件。

ADDITIONAL NOTES

Redis数据结构 字典 hashtable

The sgen tool is a bit of a black box and its behavior varies depending on what you have in your Machine.config file. For example, by default it is supposed to ouptut optimized non-debug code, but that is not always the case. To get some visibility into the tool, use the /k flag in step 3, which will cause it to keep all its temporary generated files, including the source files and command line option files it generated.

即使经过上述固定它需要实例化VimService类首次时间不是瞬时(1.5秒)。根据经验观察,似乎大部分的剩余时间是由于加工 SoapDocumentMethodAttribute 属性。在这一点上是不清楚这个时间可以减少。在pre-产生XmlSerializer的集不占SOAP相关的属性,因此这些属性需要保持在code。好消息是,VimService类的应用程序,只有第一个实例化需要较长。因此,如果额外的1.5秒​​是一个问题,人们可以尝试做此类的虚设实例在应用,以提高的登录时间的用户体验的手段的开始。

Even after the above fix the time it takes to instantiate the VimService class for the first time is not instantaneous (1.5 sec). Based on empirical observation, it appears that the majority of the remaining time is due to processing the SoapDocumentMethodAttribute attributes. At this point it is unclear how this time can be reduced. The pre-generated XmlSerializer assembly does not account for the SOAP-related attributes, so these attributes need to remain in the code. The good news is that only the first instantiation of the VimService class for that app takes long. So if the extra 1.5 seconds are a problem, one could try to do a dummy instantiation of this class at the beginning of the application as a means to improve user experience of login time.

相关推荐