- Frugal Cafe
- Posts
- FC04 Avoid LOH allocation from StringBuilder.ExpandByABlock
FC04 Avoid LOH allocation from StringBuilder.ExpandByABlock
Easy
Lenovo utility programs are providing lots of sources of our performance discussions because they’re causing lots of large object allocations.
Here is one more example with StringBuilder usage:
Here Stringify is causing 6.1% allocations in a process, just two samples, all in LOH. The first one is from StringBuilder.Append(string), the second one is from StringBuilder.ToString().
StringBuilder has a quite nice internal data structure to avoid LOH allocations in its internal buffer most of the time. But there is a short sight, if you add a big chunk of data, LOH allocations could be possible, because the implementation does not split it into multiple chunks.
Source code (as decoded by ILSpy):
In this case, the header dictionary is actually completely empty.
Here is a simple fix to avoid LOH allocations from StringBuilder.AppendLine:
If the dictionary is null or empty, we just need a single string.Concat(string, string, string, string) which has optimal implementation.
But what if the dictionary has data inside? I would write as:
We’re replacing StringBuilder with a string array that is reusable.
In case you can’t avoid StringBuilder.Append with big data, the simple solution is to split them into smaller chunks. Smaller than 40 K characters would avoid LOH allocations. For example, you can add SplitAppend extension methods.