NonContiguousMemoryStream Revised
09 Mar 2008Earlier I wrote about a class I designed to combat large heap fragmentation issues with memory streams. I’ve updated the class to correct a bug I recently discovered in the read routine. I’ve also published the entire solution with additional unit tests.
MemoryStreams
are darn handy little buggers for caching away results from serialization and file copy operations. However, there’s a dark side in that MemoryStreams
can create additional memory pressure, particularly when stream sizes grow in excess of about 85K. At that point, the .NET run-time allocates from the large memory heap. This heap does not compact like the small memory heap and can lead to fragmentation. Often, this can cause OutOfMemoryExceptions
long before physical memory is exhausted.
No amount of garbage collection will reclaim this memory due to a quirk in the .NET memory management. The NonContiguousMemoryStream
offered here mitigates this issue by using a memory store made of smaller buffers. Since the large heap is never touched, the run-time can do a better job of compacting and reclaiming memory.
My informal testing shows that NonContiguousMemoryStream
can run approximately 4 times longer than conventional memory streams before exhausting memory. The trade off is slightly lower performance owing to the overhead of managing multiple buffers. Also, the minimum size of a NonContiguousMemoryStream
is 64K due to the fixed buffer size. You’ll want to make certain of your needs before resorting to this hammer. I’m planning to write a hybrid version that will perform like a regular MemoryStream
for small sizes and switch to NonContiguousMemoryStream
as the stream grows.
Bloget uses this class as well so I’ll be issuing a second Beta to cover this and other issues. I’ve been living with this bug for a few months in Bloget without incident so the bug’s affect is somewhat of a corner case. Still it’s a concern and should be noted (and fixed).
NonContiguousMemoryStream
is available on the Downloads page.