Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is MSMQ faster than WCF QueueService?

I have self-hosted WCF service in console with netNamedPipeBinding binding. The service has just one empty method Send(DataTable bulk)

[ServiceContract]
public interface IWcfQueueService
{
    [OperationContract]
    void Send(DataTable bulk);       
}
public class WcfQueueService : IWcfQueueService
{
    public void Send(DataTable bulk)
    {           
       // Here would be something like _bulks.Add(bulk);
       // BUT, for now it is empty method and still it's slower than MSMQ
    }    
}

My client gets 200K inputs from DB and process it with our BoundedThreadPool(only creates, let say, 20 threads). Each input is processed with different thread. Each thread executes MyMethod and in the end of MyMethod the result is added to bulkManager.

public void MyMethod(string input)
{            
    var res = ProcessInput(input);
    bulkManager.Add(res);
}

When bulkManager accumulates N items (=bulk) it pass the bulk to another thread that all it does is enqueue that bulk with one of two methods:

  1. If wcf enabled: wcfQueueService.Send(bulk);
  2. else if MSMQ enabled: new MessageQueue(@".\private$\q").Send(new Message {Body = bulk});

All two methods works, but MSMQ works much more faster. With MSMQ client manages to process about 80K bulks in 20seconds while with wcf only 20K-30K bulks. I don't understand why it happens. My WCF runs in different process like MSMQ does. In addition, my WCF doesn't stores anything, it has empty method. So why MSMQ wins WCF?

Updated

As leppie suggested I tried .NetRemoting. NetRemoting indeed improved the speed. The client processed 60K. But,

  1. It's still slower than MSMQ
  2. As I read .Net Remoting is deprecated by WCF and WCF should be faster than .Net Remoting according to this, so why I get that my wcf is slower? Maybe my binding is wrong?
like image 534
theateist Avatar asked Jul 03 '12 09:07

theateist


2 Answers

You are not comparing like with like.

The most obvious difference is that in the WCF case your timings include execution of the entire service-side channel stack and operation invocation, whereas your direct MSMQ case only measures the time to enqueue the payload on the client side. Bear in mind that the service side processing in WCF includes deserialization of your DataTable object, which is probably quite expensive if your bulking factor N is large.

What is more, depending on how you have configured your service instancing and throttling knobs, the requests from the client may be being made more quickly than the service is configured to handle, resulting in the requests themselves being queued for execution on the service side.

Also, depending on how you have configured your binding, there may be other significant differences, security for example. By the way, did you really use NetNamedPipeBinding (as your question states) rather than NetMsmqBinding as the title seemed to imply? If so, using the default binding configuration you will have totally unnecessary encryption and signing of each Bulk message going on, which isn't happening in your direct MSMQ case. These cryptographic operations on large messages will be relatively expensive also.

A better comparison would be with the WCF operation defined as OneWay.

like image 177
Chris Dickson Avatar answered Oct 01 '22 13:10

Chris Dickson


Can you provide example code that show the behavior you are seeing?

I did my own testing by generating 20,000 messages to send. I tried both, 20,000 with direct MSMQ, and 20,000 with WCF abstracting the MSMQ endpoint for me.

The 20,000 with direct MSMQ used 64.75 percent of the CPU time and the WCF version sending 20,000 messages used 34.16 percent of the CPU time (instrumented using the Analyze feature of Visual Studio Ultimate).

Unless I have made an error on my end the WCF version was almost twice as fast as the hard coded MSMQ equivalent.

like image 40
Phil Patterson Avatar answered Oct 03 '22 13:10

Phil Patterson