Developer's Diary

Thoughts on innovations in the software development field, with focus on the Microsoft platform. C#, C++, .NET Framework, client and server products.

Monday, September 11, 2006

Juicing up your WCF services

This weekend has been so relaxed that I'm almost ashamed of it. However, I think I needed some quality do-nothing-at-all time, because I did start to feel tiny stress symptoms at the end of last week. Positive stress resulting in negative effects, I suppose. Feel back on track now. The swedish election is coming up, and I must say I find the debate shows on TV quite amusing; more so than earlier years.

However relaxed my weekend has been, the occasional debates and sushi eating aside, I did get quite a bit of time to play around with WCF. I couldn't resist that opportunity, could I?

Optimizing service events
I started delving into the wonderful world of duplex services, and thus, service callbacks. There is a lot to be explored here, and I have merely tapped into the very surface. Duplex services in WCF can be implemented using non-duplex protocols, such as HTTP. WCF does this by adding extra information to the SOAP header, for example by using the WS-Reliable Messaging specification and operating the service as a Composite Duplex (which essentially means combining two separate channels into one). There is a big drawback to using HTTP, though: services must use the wsDualHttpBinding binding, which is very slow. The wsDualHttpBinding binding is the only one of the HTTP bindings that support duplex services. So what can be done?

The answer is to use the netTcpBinding binding. TCP is by design a duplex protocol and is, as I explored in my last blog entry, very fast. With a TCP-based service, the callback performance does indeed improve drastically.

Just for fun, I decided to declare a customBinding binding and see if I could make the callbacks work that way as well. I started out with a custom binding that implemented the following channel stack, in order, top down:
  • reliableSession
  • textMessageEncoding
  • tcpTransport
This worked like a charm - I still got my callback messages. I removed the reliableSession channel, and it still worked. I also noted a side effect, something that had been bothering me before. Service startup times were drastically shorter than that of any other pre-packaged binding I had tested, it even surpassed the netTcpBinding.

Optimizing service startup
As it turns out, when a service that implements the netTcpBinding starts up, it performs 44 DLL loads. The service implementing the customBinding performs 25 DLL loads. The interesting differences being one or more loads of:
  • System.DirectoryServices.ni.dll
  • ntdsapi.dll
  • DNSAPI.dll
  • Secur32.dll
This hints that it might be the security features of the netTcpBinding binding that takes up the extra load time, but I am yet to confirm this. Load times were over 1 second for the netTcpBinding service; the customBinding service was roughly 10 times faster, so quite a big difference.

I can't quite grasp these scenarios yet, but I think I'm fairly close to figuring out the cause and will get back to that in a later post. Cheers!

Labels:

Friday, September 08, 2006

.NET Framework 3.0 and performance

I would like to welcome any new readers (which would be everyone, since this is my first post) to this attempt of mine to document my findings in the software development field. My big swedish fan base may be disappointed in the fact that I have decided to publish this thing in english, but I really would like to share information with all nationalities.

I've been getting my hands dirty with the new .NET Framework 3.0, and more specifically, the Windows Communication Foundation part. Up until a week ago, I had been using the June CTP, since this was the latest version with a set of functioning add-ons for Visual Studio 2005. On September 1st, Microsoft released the .NET Framework 3.0 RC1. The RC1 doesn't hold many new features compared to the July CTP, but instead focuses on increased performance and stability. I was curious to see what the differences were, if any.

Experiences and impressions
Let me first tell you that I am very impressed with how the WCF architecture is constructed. It is very versitile, designed to be the new communication architecture for many years to come, with its own customizable channel stack at heart. And yet, it is extremely simple to work with. Let me enumerate a few of the things I found very useful:
  • Ability to host services in any executable, be it the IIS, a windows service or a console application
  • Very flexible and extendable architecture
  • Enabling use of other protocols than HTTP, such as raw TCP or Named Pipes
  • Services configurable through web.config/app.config, so for instance changing the network protocol does not require a recompilation
  • Support for using multiple endpoints and different protocols at the same time
If you need a crash course in WCF, this article does a pretty good job.

RC1 performance
I have experimented with performance and found that RC1 is definitely a bit faster than the older June CTP. This is most visible when making HTTP calls, since these include more overhead and thus take more time generally than, for instance, TCP. Where a call would take 250 ms with the June CTP, I was now down to around 200 ms with the RC1. Similarly, TCP calls were generally around 10-11 ms with the June CTP, while the RC1 pushed them down to the 7 ms neighbourhood. With named pipes, I got down to 5 ms. These tests were all run with empty method bodies - to get the pure response times, built in release mode and running as a windows service on a virtual machine. I'm sure you would get even better performance on a physical machine. Enabling basic security settings unfortunately impedes performance drastically.

Think about it... 7 ms for a web service call is not much. The traditional web service HTTP call would take 30 times longer. So what does this imply?

You could design your services so that they communicate with other services on the same LAN using TCP calls, while HTTP endpoints would be exposed for consuming applications, internal or external. Technically, the only thing that has changed when using TCP instead of HTTP is just that, the transport protocol. The payload is still the same, following the same WS-* and SOAP standards, so compatibility shouldn't be a big factor. You might still want to expose a HTTP endpoint simply because most implementations assume that web services are run through a web server, and thus HTTP. I see great potential to write more efficient service oriented code here.

Labels: