How can I speed up message processing when using MSMQ with WCF?

For small gains, it is generally possible to eke out a few percentage points of performance by tuning parameters and settings according to the application domain knowledge you have. For large gains, you are likely going to have to think about larger design issues. In particular, a type of design issue that you should consider in your quest for large gains is to question what features are truly needed to build your application.

This article is about a few of those feature decisions that you can make when using MSMQ together with WCF. Since these design decisions require building your application with a restricted set of features, there's no guarantee that these techniques are going to be applicable for you. It really just depends on the queue features you need versus the features you don't. I'm not going to mention features not primarily related to the queue, such as whether to use message security, although obviously the same type of analysis can be applied.

  • Use the NetMsmqBinding instead of the MsmqIntegrationBinding. Of the two bindings, NetMsmq is faster than MsmqIntegration in most cases when similar conditions are applied (for example, both running without security). I have an earlier article describing the differences between the two MSMQ bindings.
  • Disable transactional delivery of messages. The ExactlyOnce option controls whether messages are delivered without being lost or duplicated. Making a delivery guarantee requires that the queue be transactional and issue transactions for transfers. If you need best effort rather than exactly once, turning off transactions noticeably improves performance.
  • Disable durable message storage. If you've already turned off transactions, then you can go significantly farther as well. The Durable option controls whether the queue survives restarting the MSMQ service. If you are using the queue to get asynchronous communication rather than reliable delivery, then leaving messages in a volatile store is another noticeable performance improvement.
  • Pack more messages into the same transaction. Often you can't go as far as turning transactions completely off. A less dramatic step is to use the same transaction for multiple receive operations. The TransactedBatchingBehavior allows you to group messages up to a maximum batch size in a single transaction to amortize creating a transaction across multiple receive calls.

Next time: Streaming and ToString