From d5c091c05619ecddd3075c369ad89aaeb085ee61 Mon Sep 17 00:00:00 2001 From: Steven Giesel Date: Fri, 3 Nov 2023 15:05:43 +0100 Subject: [PATCH] Refactored Grow method --- CHANGELOG.md | 2 +- .../ValueStringBuilder.cs | 13 ++++++++++- .../AppendBenchmark.cs | 23 ------------------- 3 files changed, 13 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 232edf7..909e356 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ All notable changes to **ValueStringBuilder** will be documented in this file. T ### Changed - `Dispose` resets the `ValueStringBuilder` to the initial state, so it doesn't lead to undefined behavior when used again - +- Use different approach for `Grow` to be a bit more performant ## [1.18.5] - 2023-10-19 ### Changed diff --git a/src/LinkDotNet.StringBuilder/ValueStringBuilder.cs b/src/LinkDotNet.StringBuilder/ValueStringBuilder.cs index f586a69..787f250 100644 --- a/src/LinkDotNet.StringBuilder/ValueStringBuilder.cs +++ b/src/LinkDotNet.StringBuilder/ValueStringBuilder.cs @@ -313,7 +313,18 @@ private void Grow(int capacity = 0) } var rented = ArrayPool.Shared.Rent(size); - buffer[..bufferPosition].CopyTo(rented); + + if (bufferPosition > 0) + { + ref var sourceRef = ref MemoryMarshal.GetReference(buffer); + ref var destinationRef = ref MemoryMarshal.GetReference(rented.AsSpan()); + + Unsafe.CopyBlock( + ref Unsafe.As(ref destinationRef), + ref Unsafe.As(ref sourceRef), + (uint)(bufferPosition * sizeof(char))); + } + var oldBufferFromPool = arrayFromPool; buffer = arrayFromPool = rented; diff --git a/tests/LinkDotNet.StringBuilder.Benchmarks/AppendBenchmark.cs b/tests/LinkDotNet.StringBuilder.Benchmarks/AppendBenchmark.cs index a10313f..adbead4 100644 --- a/tests/LinkDotNet.StringBuilder.Benchmarks/AppendBenchmark.cs +++ b/tests/LinkDotNet.StringBuilder.Benchmarks/AppendBenchmark.cs @@ -5,17 +5,6 @@ namespace LinkDotNet.StringBuilder.Benchmarks; [MemoryDiagnoser] public class AppendBenchmarks { - [Benchmark(Baseline = true)] - public string DotNetStringBuilder() - { - var builder = new System.Text.StringBuilder(); - builder.AppendLine("That is the first line of our benchmark."); - builder.AppendLine("We can multiple stuff in here if want."); - builder.AppendLine("The idea is that we can resize the internal structure from time to time."); - builder.AppendLine("We can also add other Append method if we want. But we keep it easy for now."); - return builder.ToString(); - } - [Benchmark] public string ValueStringBuilder() { @@ -27,16 +16,4 @@ public string ValueStringBuilder() builder.AppendLine("We can also add other Append method if we want. But we keep it easy for now."); return builder.ToString(); } - - [Benchmark] - public string ValueStringBuilderPreAllocated() - { - using var builder = new ValueStringBuilder(stackalloc char[256]); - builder.AppendLine("That is the first line of our benchmark."); - builder.AppendLine("We can multiple stuff in here if want."); - builder.AppendLine("We can multiple stuff in here if want."); - builder.AppendLine("The idea is that we can resize the internal structure from time to time."); - builder.AppendLine("We can also add other Append method if we want. But we keep it easy for now."); - return builder.ToString(); - } } \ No newline at end of file