Skip to content

Commit ad466c8

Browse files
committed
Replace performance tuning
1 parent e07a8e7 commit ad466c8

File tree

2 files changed

+27
-2
lines changed

2 files changed

+27
-2
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ All notable changes to **ValueStringBuilder** will be documented in this file. T
1010

1111
- implicit cast operator from `string` and `ReadOnlySpan<char>` to the `ValueStringBuilder` with pre-initialized buffer
1212

13+
### Changed
14+
15+
- various path optimizations for replace logic to use less allocations while being faster
16+
1317
### Removed
1418

1519
- Removed value type overloads for `Append` and `Insert` and just offer `Append(ISpanFormattable)` and `Insert(ISpanFormattable)`, which covers more cases.

src/LinkDotNet.StringBuilder/ValueStringBuilder.Replace.cs

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,8 +135,29 @@ public void Replace(scoped ReadOnlySpan<char> oldValue, scoped ReadOnlySpan<char
135135
for (var i = 0; i < hits.Length; i++)
136136
{
137137
var index = startIndex + hits[i] + (delta * i);
138-
Remove(index, oldValue.Length);
139-
Insert(index, newValue);
138+
139+
// newValue is smaller than old value
140+
// We can insert the slice and remove the overhead
141+
if (delta < 0)
142+
{
143+
newValue.CopyTo(buffer[index..]);
144+
Remove(index + 1, -delta);
145+
}
146+
147+
// Same length -> We can just replace the memory slice
148+
else if (delta == 0)
149+
{
150+
newValue.CopyTo(buffer[index..]);
151+
}
152+
153+
// newValue is larger than the old value
154+
// First add until the old memory region
155+
// and insert afterwards the rest
156+
else
157+
{
158+
newValue[..oldValue.Length].CopyTo(buffer[index..]);
159+
Insert(index + oldValue.Length, newValue[oldValue.Length..]);
160+
}
140161
}
141162
}
142163
}

0 commit comments

Comments
 (0)