Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MaxCapacity of StringBuilder

why does this code throw an OutOfMemoryException on i = 690864192?

StringBuilder sb = new StringBuilder();
                for (int i = 0; i < Int32.MaxValue; i++)
                {
                    sb.Append("s");
                }
                Console.WriteLine(sb.ToString());
                Console.Read();

The default capacity is 16 chars, but this grows at it needs to up to the max which is int.MaxValue = 2,147,483,647. So why is it when number of chars is 690,864,192 which is much less than the max capacity, does it throw an exception?

like image 308
David Klempfner Avatar asked Dec 19 '13 03:12

David Klempfner


People also ask

What is the maximum size of StringBuilder in C#?

Append("123456789"); sbMax. Append("0"); This code creates a StringBuilder object, sbMax , which has a maximum length of 10 characters.

What is the maximum size of StringBuilder in Java?

Here because of parameter as int the maximum capacity that a StringBuilder Class can is reach will be 2147483647 .

What's the purpose of a StringBuilder?

StringBuilder class can be used when you want to modify a string without creating a new object. For example, using the StringBuilder class can boost performance when concatenating many strings together in a loop.

How is StringBuilder different from string?

String is immutable whereas StringBuffer and StringBuilder are mutable classes. StringBuffer is thread-safe and synchronized whereas StringBuilder is not. That's why StringBuilder is faster than StringBuffer. String concatenation operator (+) internally uses StringBuffer or StringBuilder class.


2 Answers

so basically I don't have enough RAM to store a StringBuilder instance with that many chars?

No no no no no.

RAM is irrelevant; RAM has not been the relevant measure of memory for almost two decades now! Virtual address space is the relevant measure.

It is astonishing the number of people who believe that memory still works the way it did in DOS machines in the 1980s. My advice is to learn about how modern operating systems handle memory. RAM is a performance optimization. Memory is page file.

Think about it this way. You have a parking lot (page file) that can hold a million cars (memory pages). You have a driveway (RAM) that can hold ten cars. You have a keyring that can hold a thousand keys (virtual memory). You own a thousand cars. The ten you use most frequently are in the driveway. The other 990 are in the parking lot down the street.

When you run out of room in the driveway, you just move one of the cars to the parking lot. (RAM makes accessing frequently used pages fast.)

But when you buy car # 1001, the resource you've run out of is space on the keyring, not room in the parking lot or room in the driveway. You can make more room in the driveway any time, and you have loads of extra room in the parking lot, but your keyring is only so big.

Why is it when number of chars is 690,864,192 which is much less than the max capacity, does it throw an exception?

You only get 2 GB of user-addressable virtual address space per process on a 32 bit Windows machine.

At two byte per char, 690 million chars is 1.4 billion bytes, which is a huge fraction of the 2GB address space. You are leaving only around .6 GB to fit everything else in the process. At some point the string builder will need to allocate another block and there is not a free block of that size anywhere in your address space, so the allocation fails.

Why are you trying to do this in the first place? A 1.4 billion byte string is utterly ludicrous.

like image 196
Eric Lippert Avatar answered Sep 28 '22 11:09

Eric Lippert


Each time the StringBuilder allocates a new char[] (by pointing to a previous chunk instance.. which is another StringBuilder).. you're putting an insane amount of pressure on the garbage collector.

There are memory restrictions on the size of objects. Your object will likely max out your assigned memory for your applications process before reaching the end... hence OutOfMemoryException in either case.

The last StringBuilder instance you have points to the last instance before it maxed out.. that one also points to the previous instance before it maxed out... etc. You have a gigantic graph of roots for the GC that never get cleaned up.

like image 30
Simon Whitehead Avatar answered Sep 28 '22 10:09

Simon Whitehead