Skip to content

Commit

Permalink
Replace performance tuning
Browse files Browse the repository at this point in the history
  • Loading branch information
linkdotnet committed Nov 15, 2022
1 parent e07a8e7 commit ad466c8
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 2 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ All notable changes to **ValueStringBuilder** will be documented in this file. T

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

### Changed

- various path optimizations for replace logic to use less allocations while being faster

### Removed

- Removed value type overloads for `Append` and `Insert` and just offer `Append(ISpanFormattable)` and `Insert(ISpanFormattable)`, which covers more cases.
Expand Down
25 changes: 23 additions & 2 deletions src/LinkDotNet.StringBuilder/ValueStringBuilder.Replace.cs
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,29 @@ public void Replace(scoped ReadOnlySpan<char> oldValue, scoped ReadOnlySpan<char
for (var i = 0; i < hits.Length; i++)
{
var index = startIndex + hits[i] + (delta * i);
Remove(index, oldValue.Length);
Insert(index, newValue);

// newValue is smaller than old value
// We can insert the slice and remove the overhead
if (delta < 0)
{
newValue.CopyTo(buffer[index..]);
Remove(index + 1, -delta);
}

// Same length -> We can just replace the memory slice
else if (delta == 0)
{
newValue.CopyTo(buffer[index..]);
}

// newValue is larger than the old value
// First add until the old memory region
// and insert afterwards the rest
else
{
newValue[..oldValue.Length].CopyTo(buffer[index..]);
Insert(index + oldValue.Length, newValue[oldValue.Length..]);
}
}
}
}

0 comments on commit ad466c8

Please sign in to comment.