WCF: Efficient Buffer Management

In order for a Transport to read and write Messages, it may buffer the serialized message. At the very least, the Headers need to be buffered. And in many cases (such as to avoid head of the line blocking issues), buffering the entire message is necessary.

While the CLR’s garbage collector does a really good job of recycling memory, there are still costs involved with each allocation. These costs include zeroing out the buffer, as well as the GC churn. As our performance dev says “no work is better than some work”. A bunch of Indigo R & D has gone into creating an efficient way to pool buffers given two knobs:

  • MaxBufferPoolSize – the total number of bytes to pool
  • MaxItemSize – maximum size of an item stored in the pool

With proper tuning, large (>10%) increases in performance can be witnessed. This functionality is exposed through System.ServiceModel.Channels.BufferManager. If you are writing a custom channel, you can create a BufferManager through the static method:

BufferManager.CreateBufferManager(long maxBufferPoolSize, int maxSize)

Then instead of calling “new byte[n];“, you can call “bufferManager.TakeBuffer(n);“. Just remember to call bufferManager.ReturnBuffer(buffer) (in a finally block if necessary) when you are finished. Lastly, you can call bufferManager.Clear(); if you ever want to flush the cache (e.g. after a certain amount of idle time).

On the built-in WCF Bindings and Transport Binding Elements, we expose MaxBufferPoolSize as a property for you to control our cache footprint. If you are sending small (< 64K) messages, then the default value of 512K is likely acceptable. For larger messages, it's often best to avoid pooling altogether, which you can accomplish by setting MaxBufferPoolSize=0. You should of course profile your code under different values to determine the settings that will be optimal for your application.

6 thoughts on “WCF: Efficient Buffer Management

  1. Pingback: kennyw.com » Blog Archive » TcpTransport’s Buffer Management in WCF

  2. Steve

    Thanks, I have been searching and flogging my WCF app for quite a while to work out why it was consuming too much memory, and it turned out MaxBufferPoolSize was the answer, I was setting this way too big (having been ignorant of what it was when originally configuring things). With big messages (~2MB) this was a total disaster for the large object heap which, with heavy usage, ends up getting very out of hand.

    Reply
  3. Pingback: Efficient Buffer management – Reduced LOH allocation | MSDN Blogs

Leave a Reply

Your email address will not be published. Required fields are marked *