Skip to content

System.Text.StringBuilder.Insert uses a lot of memory in certain scenarios #25272

@AlexGhiondea

Description

@AlexGhiondea

Ported from: https://developercommunity.visualstudio.com/content/problem/63747/systemtextstringbuilderinsert.html

Method System.Text.StringBuilder.Insert in a couple with System.Text.StringBuilder.Clear in some cases leads to very dramatic performance degradation and very high memory consumption. For the following test the StringBuilder class is absolutely unsuilable. But this case is only a simple try to reuse object in order to reduce the loading of GC. But the test shows that the result is absolutely opposite to expected.

Test case:

        [TestMethod]
        public void TestStringBuilderInsert()
        {
            const int iterationGranularity = 10000;
            var buffer = new StringBuilder();
            var s = new string(' ', 10);
            Console.WriteLine($"{buffer.Length}->{buffer.Capacity}");
            var sw = Stopwatch.StartNew();
            for (int k = 0; k < 10; k++)
            {
                for (int i = 1; i <= iterationGranularity; i++)
                {
                    buffer.Clear();
                    buffer.Append(s);
                    buffer.Append(s);
                    buffer.Append(s);
                    buffer.Insert(0, s);
                    buffer.Insert(0, s);
                }
                Console.WriteLine($"{sw.ElapsedMilliseconds,5}: {buffer.Length}->{buffer.Capacity}");
            }
            sw.Stop();
        }

Test result:

0->16
   71: 50->100042
  251: 50->200042
  548: 50->300042
 1456: 50->400042
 2807: 50->500042
 4311: 50->600042
 6091: 50->700042
 8007: 50->800042
 9999: 50->900042
12203: 50->1000042

So, the question: If I never put into builder more than 50 characters at the iteration why the Capacity is over 1e6?
Moreover if you use memory profiler, you will understand that the memory usage is much worse that it seems at first glance.
Screenshot of profiler I will attach. Do you think that allocation 100 Gb of memory is enought? I operated only with 10 Mb...

Name Inclusive Allocations Exclusive Allocations Inclusive Bytes Exclusive Bytes Inclusive Allocations %
System.Char[] 200 018 200 018 100 015 401 486 100 015 401 486 66,63

Metadata

Metadata

Assignees

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions