Skip to content

Only materialize the requested range in StringBuilder.Append(StringBuilder, int, int) - #698

Merged
SimonCropp merged 1 commit into
mainfrom
perf/stringbuilder-append-range
Oct 12, 2026
Merged

SimonCropp merged 1 commit into
mainfrom
perf/stringbuilder-append-range

Conversation

@SimonCropp

Copy link
Copy Markdown
Owner

The StringBuilder.Append(StringBuilder, int, int) polyfill (active on .NET Framework / netstandard2.0) ended with target.Append(value.ToString(), startIndex, count), materializing the entire source builder as a string to append a slice of it. Appending small ranges out of a large builder allocated and copied the whole source each time.

It now appends value.ToString(startIndex, count), which only copies the requested range. string's Append(string, int, int) used to do the range check, so that check is made explicitly first (startIndex > value.Length - count throws ArgumentOutOfRangeException for startIndex, the same exception and parameter name as before). The earlier checks, the null handling and the count == 0 early return are untouched.

Measurements

net48, Release, x64, best of 3, 1,000 appends of a 16 char range out of a 1,000,000 char source builder:

before after
1,054.65 ms 0.64 ms

(Before also allocated a 2 MB string per call.)

Tests

Added to PolyfillTests_StringBuilder.cs:

  • StringBuilder_Append_StringBuilder_Ranges: start, middle, end, whole and empty ranges, checking the returned instance and that the source is unchanged
  • StringBuilder_Append_StringBuilder_MultiChunkSource: ranges of a 30,000 char source built from many small appends, including ones spanning chunk boundaries
  • StringBuilder_Append_StringBuilder_Self (appending a builder to itself)
  • StringBuilder_Append_StringBuilder_OutOfRange: ranges past the end, including int.MaxValue for either argument
  • StringBuilder_Append_StringBuilder_Null

@SimonCropp SimonCropp modified the milestones: 11.4.4, 11.4.5 Oct 12, 2026
@SimonCropp
SimonCropp merged commit a6e8de2 into main Oct 12, 2026
7 checks passed
@SimonCropp
SimonCropp deleted the perf/stringbuilder-append-range branch October 12, 2026 12:08
This was referenced Oct 12, 2026
This was referenced Oct 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant