views:

301

answers:

2

I am generating proxy classes to a clients java webservice wsdls and xsd files with svcutil. The first call made to each service proxy class takes a very long time. I was hoping to speed this up by generating the XmlSerializers assembly myself (based on the article How to: Improve the Startup Time of WCF Client Applications using the XmlSerializer), but when I do the first call to each service still takes the same amount of time. Here are the steps I am following:

//generate strong name key file
sn -k Blah.snk

//generate the proxy class file
svcutil blah.wsdl blah2.wsdl blah3.wsdl ... base.xsd blah.xsd ... /UseSerializerForFaults /ser:XmlSerializer /n:*,SomeNamespace /out:Blah.cs

//compile the class into an assembly signing it with the strong name key file
csc /target:library /keyfile:Blah.snk /out:Blah.dll Blah.cs

//generate the XmlSerializer code this will give us Blah.XmlSerializers.dll.cs
svcutil /t:xmlSerializer Blah.dll

//compile the xmlserializer code into its own dll using the same key to sign it and referencing the original dll
csc /target:library /keyfile:Blah.snk /out:Blah.XmlSerializers.dll Blah.XmlSerializers.dll.cs /r:Blah.dll

I then create a standard Console application that references both Blah.dll and Blah.XmlSerializers.dll. I will then try something like:

//BlahProxy is one of the generated service proxy classes
BlahProxy p = new BlahProxy();
//this call takes 30ish seconds
p.SomeMethod();

BlahProxy p2 = new BlahProxy();
//this call takes < 1 second
p2.SomeMethod();

//BlahProx2y is one of the generated service proxy classes
BlahProxy2 p3 = new BlahProxy2();
//this call takes 30ish seconds
p3.SomeMethod();

BlahProxy2 p4 = new BlahProxy2();
//this call takes < 1 second
p4.SomeMethod();

I know that the problem is not server side because I don't see the request made in Fiddler until around 29 seconds. Subsequent calls to each service take < 1 second, so thats why I was hoping the main slow down was the .net runtime generating the xmlserializer code itself, compiling it and loading the assembly. I figured this would be the reason the first call to each service is slow and the rest are fast. Unfortunatley, me generating the code myself is not speeding anything up. Does anyone see what I am doing wrong?

A: 

What kind of endpoints your service expose? Sometimes the delay happens because of security handshakes. Also I can suggest you to use net.tcp protocol, if it's respond to your app requirements, it's faster than others.

I can also suggest you to start your service with some job, because it delay always doing first call to the proxy, and the following calls (even by other users) are faster.

Tell me if this helped.

Daria Barteneva
I have no control over the service itself. I have thought about creating instances of the service proxy classes when my app pool starts up (to avoid the delay on the first "real" call to the service), but I was hoping to avoid that by generating the XmlSerializer code correctly, or at least finding out why my XmlSerializer assembly is not currently helping.
Matt Dearing
I'm using xaml serializers and I have no complains... first call delay me from 2-4 seconds, but I have security conversations... so I really don't know why yours are so slow on client side. Just for experience, try to create your service and consume it with the same client and the same serializer... see what's happends...
Daria Barteneva
+2  A: 

I believe that the problem is not with XML serialization, but with the first call being made to the proxy. The first call to a proxy is always going to take a long time, because WCF has to set up a good amount of plumbing.

If you know you are going to make successive calls on the proxy (and you don't have session issue worries) then you should create the proxy as early as possible and call Open on it. Once you do that, you should make the calls to the proxy as you need them and only dispose when done.

Wenlong Dong elaborates on best practices revolving around proxy creation, which has more suggestions on how you can optimize proxy performance.

casperOne
+1 Great article so what he is saying makes sense with my example above, and the channel factory caching at the appdomain level in 3.5 (although 27 seconds seems like an insane amount of time for "plumbing"). So I guess my only option may be to open up an instance of each proxy (when my app pool starts) to get their channel factories loaded into the app domain. I agree with you that the problem must not be XmlSerialization because if I "disable" channel factory caching, as the article explains, the second call also takes 27 seconds and I assume they would both use the same XmlSerializer code.
Matt Dearing
I wonder if the amount of time the "pluming" is taking is a result of the size of these proxy class's file. The client's wsdls and xsds are enormous because they keep a history of every method and object (MethodA_1, MethodA_2, ... MethodA_12, MethodAInput_1, MethodAInput_2, etc). This makes the svcutil generated file > 11MB.
Matt Dearing
@Matt Dearing: Yeah, I'm going to have to say that the channel generation (because endpoint descriptions and the like all have to be set up) are definitely the issue here. With an 11MB WSDL file, that's just insane, and the amount of work that WCF has to do to make all of that available on one proxy is tremendous. It's a shame you don't have control over the service, otherwise, I'd suggest breaking it out into separate services.
casperOne
No i mean the 1 file generated by svcutil is 11MB. There are many seperate wsdls and seperate xsd files, but the only way I have seen possible to share the data types is by generating all the proxy code in 1 svcutil call. If I make seperate svcutil calls they each get their own copy of all the data types which gives me thirteen 6MB files (1 per service) instead of one 11MB file. I actually have a question listed here: http://stackoverflow.com/questions/2812117/wcf-xmlserializer-split-files , if you care to weigh in since no one else has =).
Matt Dearing