WCF Proxy Performance vs WSE V3
Recently, I had been asked to examine a situation where WSE V3 service calls were substantially quicker than the equivalent WCF version.
The reason in this instance was the fact that the WCF proxy was being created for each and every service call made (which was also the case with WSE V3).
WCF proxies are far more heavyweight and incur significant penalty if they are being created all the time. WSE V3 proxies by comparison are pretty lightweight.
So the code was changed such that one proxy was created and all requests used that already created proxy. We used a static class to wrap the creation of the proxy and access to the instance so that only 1 proxy is created. We also changed to default behaviour of the service to have an InstanceContextMode of "PerCall". This improved the resource usage and was more inline with the expected model. The services themselves require no session/state and were ideal candidates for PerCall instancing in WCF.
However, in the world of ASP.NET, we have traditionally used the practice of creating, using, then destroying (or leaving for the GC if no IDispose). In addition, its hard to get away from this model in ASP.NET unless you do something extra. For high performance ASP.NET applications with thousands of concurrent users, creating proxy classes to make service calls is very costly.
Again, in our case, we used a static class to host a single instance of the proxy. It was always open, and never closed. Coupled with the PerCall instancing model, this seened to work well.
What I am not 100% sure of is the thread safety of the proxy. If using a single static instance, what happens when multiple threads make concurrent service calls using the same proxy? The MSDN doco states the usual: "Static members are guaranteed thrad safe, instance members are not". In the initial tests, everything worked very well, but we had yet to excercise this approach under extreme load.
Should this approach fail under extreme load, I had created a "ProxyPool" implementation which simply acted as a generic object pool but with semantics specific to WCF proxies. A pool of some amount was created and on initialisation, the pool was filled with a series of proxy objects, created, opened and ready to use. A GET and RELEASE method was provided to use a proxy from the pool and return it to the pool once done. So it will be interesting to see what occurs under high load and what the best practice approach is for ASP.NET apps. Note that this approach is well suited to the PerCall instancing model, where service instances are destroyed after each call. The PerSession instancing model would require a little more smarts by the proxy pool if this was used.
Any comments or suggestions would be extremely welcome.