28

This is probably a really simple question, I think all that I am after is Best Practice for declaring a new MemoryStream

What is the difference between the following 2 samples:

MemoryStream myStream = new MemoryStream(0x10000);

or

MemoryStream myStream = new MemoryStream();

Obviously, I know that the first example set the initial capacity of the stream. But, both of these have an automatically resizable capacity.

I there any reason why I should use one method as opposed to the other?

iandotkelly
  • 9,024
  • 8
  • 48
  • 67
David Hamilton
  • 283
  • 1
  • 3
  • 4

7 Answers7

31

There is overhead associated with re-sizing a memory stream. If you know or otherwise have a reasonable guess as to the expected size needed to be stored in the memory stream, you'll want to use that size as the initial capacity. Otherwise, the default size of 0 is used and will be resized as data is added.

iammichael
  • 9,477
  • 3
  • 32
  • 42
  • 1
    Is the default size really 4096? [MSDN says it is zero](http://msdn.microsoft.com/en-us/library/ad966f9s.aspx) – Dave Hillier Jun 17 '13 at 21:51
  • It's been a long time. I don't know where I got that initial size of 4096. I can't seem to corroborate it now. Edited. – iammichael Jun 18 '13 at 03:03
  • 10
    Interesting factoid for .net 4, using ILSpy I found it does do a initial size of 0, but when you write the first byte it will call the private function `EnsureCapacity` that has a minimum size of 256. Every growth after that initial 256 doubles the current capacity. – Scott Chamberlain Jun 18 '13 at 04:22
10

Old question I know, but just for the record;

If you are dealing with a really large amount of data (more than one GB in my case), setting the initial capacity was the only way to make it work in an acceptable period of time and without killing the server. In this scenario the re-sizing overhead was crucial.

Felipe Pereira
  • 11,410
  • 4
  • 41
  • 45
2

When a memory stream is re-sized, it creates a new byte[] buffer of new size. If this operation is being performed frequently, you can face one of two problems depending on buffer size: 1. The system throws OurOfMemoryException 2. All memory in the heap gets fragmented. It gives unpredictable consequences. For example constructor of System.Drawing.Bitmap fails with 'Parameter is not valid' message.

Alex
  • 361
  • 4
  • 5
2

If you know the size you're going to need, I believe setting the size explicitly will improve performance, because the framework won't have to resize the stream several times.

Ilya Kogan
  • 21,995
  • 15
  • 85
  • 141
1

If you know already exactly how many bytes you want to store setting it explicitly in the constructor seems the right thing - In general I would keep it as simple as possible and just use the default constructor with no parameters, it's just one more thing you have to read and understand when maintaining the code otherwise.

BrokenGlass
  • 158,293
  • 28
  • 286
  • 335
1

If you know that you will nee 0x10000 bytes of data, the first code snippet ensures that the memory stream is initialized to this size and will never need to increase. There might be some performance implications depending on how the class manages the buffer underneath and whether it needs a contiguous block of memory; depending on the specifics, resizing might be an expensive operation.

Szymon Rozga
  • 17,971
  • 7
  • 53
  • 66
  • "[...] Will never need to increase." - I have a feeling this is false, if anyone is reading through this. – Zoey May 22 '13 at 16:21
  • 1
    Yes, only if you pass in a byte array to the constructor does MemoryStream not become resizeable. See the [MSDN](http://msdn.microsoft.com/en-us/library/bx3c0489.aspx) *"Initializes a new instance of the MemoryStream class with an expandable capacity initialized as specified."* – Scott Chamberlain Jun 18 '13 at 04:14
0

In first case you avoid automatic structure resize cost while needed size is less than value passed to constructor.

Przemysław Michalski
  • 9,627
  • 7
  • 31
  • 37