If you are lazy to read whole post, jump to “Summary”.
Do you know situation when project is designed for one needs and in the end of the day customers wants it to be performing 100 times faster? You have to be ready for such things and have something to cover your ass.
We changed configuration of our application to pick up more items for processing and it started to process more, but of course it did not meet customer needs, so we did much more other tweaks to make our service performing better. And it started (a bit), but along with improvements we got memory leaks.
So our app started to eat memory dramatically. Within 5-15 minutes it was already hitting 2Gb score. Why?
Of course in the beginning it is always not obvious, so I started with downloading ANTS Memory Profiler. (by the way it is simply amazing profiler). After I learned “what means what” in profiler I was able to analyze what I see. I discovered, that our application produces huge memory fragmentation with large objects. (see screenshots below)
Here are some recommendations from profiler website:
Solving large object heap fragmentation
Large object heap fragmentation can be one of the most difficult types of memory problem to solve, because it often involves changes to the architecture of the application. The best approach to use will depend on the exact nature of your program:
•Split arrays into smaller units so that they remain below 85kB (and so are never allocated on the large object heap).
•Alternatively, you can allocate the largest and longest-living objects first (if your objects are files which are queued for processing, for example).
•In some cases, it may be that periodically stopping and restarting the program is the only option.
My thought was that with increasing number of A/B/C to be processed in one message we overload memory with many large collections that were not garbage collected, so in the end they kept references to our entities.

Also what was interesting is that Byte[], keeping 134Mb of memory… I dig deeper into capabilities of profiler and found following:

This made me thinks that large objects are actually allocated by WCF and never disposed, so in the end of the day it was actually been eating memory.
Ok, so I knew that it is something related to WCF BufferManager. I started looking what was changed in WCF configuration in order to process bigger messages. Here is what I found:
<binding name="Allscripts.Homecare.WSHTTPBinding.Configuration" closeTimeout="00:05:00" openTimeout="00:05:00" receiveTimeout="00:10:00" sendTimeout="00:05:00" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647"/>
Do you see anything to be odd about it? Yes all values are set to max. But was those values really evaluated or blindly changed to max? Obviously maxBufferPoolSize is related to BufferManager. A bit of search and I found this:
From http://kennyw.com/work/indigo/51 :
“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.”
So with changing maxBufferPoolSize to 0 I was able to witness stability in work of our service. Of course it was consuming a lot of memory because of hard time we gave to it, but it was working.
From the picture below you can see that there is no problem with Large Objects Heap. It was nicely bumping up and down (blue line).

Summary
If you have performance problems, and try to fix them by changing all limiters (timeouts, buffer sizes, other stuff) do this attentively. Evaluate how each of variables result in your performance. If you already have problems, use advanced profilers, so they give you much information about where your memory/time goes. Surprisingly increasing WCF maxBufferPoolSize doesn’t always mean increase in performance parameters, it can even result in huge memory drawbacks if size of messages you send is larger than 64K. For me it was also surprise, as it sounds that GC is not keen on disposing large objects from heap.
Hope this helps someone…