Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/corefx.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlexander Radchenko <radchenkosasha@gmail.com>2018-04-10 00:48:09 +0300
committerAhson Khan <ahkha@microsoft.com>2018-04-10 00:48:09 +0300
commit622564b3ca5fc622a2fef5c42d301a7173b6054f (patch)
tree48516f34ba179fa9fbe261ecc05b9e78f92abdd5 /src
parentb606666632275398d56f4de574e46550e6e098d7 (diff)
Created performance tests for ReadOnlySequence (#28927)
* Created performance tests for ReadOnlySequence * Review issues * Removed InnerCount * 10
Diffstat (limited to 'src')
-rw-r--r--src/System.Memory/tests/Performance/Perf.ReadOnlySequence.Enumerator.cs301
-rw-r--r--src/System.Memory/tests/Performance/Perf.ReadOnlySequence.First.cs302
-rw-r--r--src/System.Memory/tests/Performance/Perf.ReadOnlySequence.GetPosition.cs215
-rw-r--r--src/System.Memory/tests/Performance/Perf.ReadOnlySequence.Slice.cs973
-rw-r--r--src/System.Memory/tests/Performance/Perf.ReadOnlySequence.TryGet.cs314
-rw-r--r--src/System.Memory/tests/Performance/System.Memory.Performance.Tests.csproj11
6 files changed, 2116 insertions, 0 deletions
diff --git a/src/System.Memory/tests/Performance/Perf.ReadOnlySequence.Enumerator.cs b/src/System.Memory/tests/Performance/Perf.ReadOnlySequence.Enumerator.cs
new file mode 100644
index 0000000000..4d6d45c188
--- /dev/null
+++ b/src/System.Memory/tests/Performance/Perf.ReadOnlySequence.Enumerator.cs
@@ -0,0 +1,301 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Memory.Tests;
+using System.MemoryTests;
+using Microsoft.Xunit.Performance;
+using Xunit;
+
+namespace System.Buffers.Tests
+{
+ public class Perf_ReadOnlySequence_Enumerator
+ {
+ private const int InnerCount = 100_000;
+ volatile static int _volatileInt = 0;
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ [InlineData(10_000, 100)]
+ private static void Byte_Array(int bufSize, int bufOffset)
+ {
+ var buffer = new ReadOnlySequence<byte>(new byte[bufSize], bufOffset, bufSize - 2 * bufOffset);
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ foreach(ReadOnlyMemory<byte> memory in buffer)
+ localInt ^= memory.Length;
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ [InlineData(10_000, 100)]
+ private static void Byte_Memory(int bufSize, int bufOffset)
+ {
+ var manager = new CustomMemoryForTest<byte>(new byte[bufSize], bufOffset, bufSize - 2 * bufOffset);
+ var buffer = new ReadOnlySequence<byte>(manager.Memory);
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ foreach(ReadOnlyMemory<byte> memory in buffer)
+ localInt ^= memory.Length;
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ [InlineData(10_000, 100)]
+ private static void Byte_SingleSegment(int bufSize, int bufOffset)
+ {
+ var segment1 = new BufferSegment<byte>(new byte[bufSize]);
+ var buffer = new ReadOnlySequence<byte>(segment1, bufOffset, segment1, bufSize - bufOffset);
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ foreach(ReadOnlyMemory<byte> memory in buffer)
+ localInt ^= memory.Length;
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount / 10)]
+ [InlineData(10_000, 100)]
+ private static void Byte_MultiSegment(int bufSize, int bufOffset)
+ {
+ var segment1 = new BufferSegment<byte>(new byte[bufSize / 10]);
+ BufferSegment<byte> segment2 = segment1;
+ for (int j = 0; j < 10; j++)
+ segment2 = segment2.Append(new byte[bufSize / 10]);
+ var buffer = new ReadOnlySequence<byte>(segment1, bufOffset, segment2, bufSize / 10 - bufOffset);
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ foreach(ReadOnlyMemory<byte> memory in buffer)
+ localInt ^= memory.Length;
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ private static void Byte_Empty()
+ {
+ ReadOnlySequence<byte> buffer = ReadOnlySequence<byte>.Empty;
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ foreach(ReadOnlyMemory<byte> memory in buffer)
+ localInt ^= memory.Length;
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ private static void Byte_Default()
+ {
+ ReadOnlySequence<byte> buffer = default;
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ foreach(ReadOnlyMemory<byte> memory in buffer)
+ localInt ^= memory.Length;
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ [InlineData(10_000, 100)]
+ private static void Char_Array(int bufSize, int bufOffset)
+ {
+ var buffer = new ReadOnlySequence<char>(new char[bufSize], bufOffset, bufSize - 2 * bufOffset);
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ foreach(ReadOnlyMemory<char> memory in buffer)
+ localInt ^= memory.Length;
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ [InlineData(10_000, 100)]
+ private static void Char_Memory(int bufSize, int bufOffset)
+ {
+ var manager = new CustomMemoryForTest<char>(new char[bufSize], bufOffset, bufSize - 2 * bufOffset);
+ var buffer = new ReadOnlySequence<char>(manager.Memory);
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ foreach(ReadOnlyMemory<char> memory in buffer)
+ localInt ^= memory.Length;
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ [InlineData(10_000, 100)]
+ private static void Char_SingleSegment(int bufSize, int bufOffset)
+ {
+ var segment1 = new BufferSegment<char>(new char[bufSize]);
+ var buffer = new ReadOnlySequence<char>(segment1, bufOffset, segment1, bufSize - bufOffset);
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ foreach(ReadOnlyMemory<char> memory in buffer)
+ localInt ^= memory.Length;
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount / 10)]
+ [InlineData(10_000, 100)]
+ private static void Char_MultiSegment(int bufSize, int bufOffset)
+ {
+ var segment1 = new BufferSegment<char>(new char[bufSize / 10]);
+ BufferSegment<char> segment2 = segment1;
+ for (int j = 0; j < 10; j++)
+ segment2 = segment2.Append(new char[bufSize / 10]);
+ var buffer = new ReadOnlySequence<char>(segment1, bufOffset, segment2, bufSize / 10 - bufOffset);
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ foreach(ReadOnlyMemory<char> memory in buffer)
+ localInt ^= memory.Length;
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ [InlineData(10_000, 100)]
+ private static void String(int bufSize, int bufOffset)
+ {
+ ReadOnlyMemory<char> strMemory = new string('a', bufSize).AsMemory();
+ strMemory = strMemory.Slice(bufOffset, bufSize - bufOffset);
+ var buffer = new ReadOnlySequence<char>(strMemory);
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ foreach(ReadOnlyMemory<char> memory in buffer)
+ localInt ^= memory.Length;
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ private static void Char_Empty()
+ {
+ ReadOnlySequence<char> buffer = ReadOnlySequence<char>.Empty;
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ foreach(ReadOnlyMemory<char> memory in buffer)
+ localInt ^= memory.Length;
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ private static void Char_Default()
+ {
+ ReadOnlySequence<char> buffer = default;
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ foreach(ReadOnlyMemory<char> memory in buffer)
+ localInt ^= memory.Length;
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ }
+}
diff --git a/src/System.Memory/tests/Performance/Perf.ReadOnlySequence.First.cs b/src/System.Memory/tests/Performance/Perf.ReadOnlySequence.First.cs
new file mode 100644
index 0000000000..3d5b69e1bf
--- /dev/null
+++ b/src/System.Memory/tests/Performance/Perf.ReadOnlySequence.First.cs
@@ -0,0 +1,302 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Memory.Tests;
+using System.MemoryTests;
+using Microsoft.Xunit.Performance;
+using Xunit;
+
+namespace System.Buffers.Tests
+{
+ public class Perf_ReadOnlySequence_First
+ {
+ private const int InnerCount = 100_000;
+ volatile static int _volatileInt = 0;
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ [InlineData(10_000, 100)]
+ private static void Byte_Array(int bufSize, int bufOffset)
+ {
+ var buffer = new ReadOnlySequence<byte>(new byte[bufSize], bufOffset, bufSize - 2 * bufOffset);
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ ReadOnlyMemory<byte> first = buffer.First;
+ localInt ^= first.Length;
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ [InlineData(10_000, 100)]
+ private static void Byte_Memory(int bufSize, int bufOffset)
+ {
+ var manager = new CustomMemoryForTest<byte>(new byte[bufSize], bufOffset, bufSize - 2 * bufOffset);
+ var buffer = new ReadOnlySequence<byte>(manager.Memory);
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ ReadOnlyMemory<byte> first = buffer.First;
+ localInt ^= first.Length;
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ [InlineData(10_000, 100)]
+ private static void Byte_SingleSegment(int bufSize, int bufOffset)
+ {
+ var segment1 = new BufferSegment<byte>(new byte[bufSize]);
+ var buffer = new ReadOnlySequence<byte>(segment1, bufOffset, segment1, bufSize - bufOffset);
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ ReadOnlyMemory<byte> first = buffer.First;
+ localInt ^= first.Length;
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ [InlineData(10_000, 100)]
+ private static void Byte_MultiSegment(int bufSize, int bufOffset)
+ {
+ var segment1 = new BufferSegment<byte>(new byte[bufSize / 10]);
+ BufferSegment<byte> segment2 = segment1;
+ for (int j = 0; j < 10; j++)
+ segment2 = segment2.Append(new byte[bufSize / 10]);
+ var buffer = new ReadOnlySequence<byte>(segment1, bufOffset, segment2, bufSize / 10 - bufOffset);
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ ReadOnlyMemory<byte> first = buffer.First;
+ localInt ^= first.Length;
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ private static void Byte_Empty()
+ {
+ ReadOnlySequence<byte> buffer = ReadOnlySequence<byte>.Empty;
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ ReadOnlyMemory<byte> first = buffer.First;
+ localInt ^= first.Length;
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ private static void Byte_Default()
+ {
+ ReadOnlySequence<byte> buffer = default;
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ ReadOnlyMemory<byte> first = buffer.First;
+ localInt ^= first.Length;
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ [InlineData(10_000, 100)]
+ private static void Char_Array(int bufSize, int bufOffset)
+ {
+ var buffer = new ReadOnlySequence<char>(new char[bufSize], bufOffset, bufSize - 2 * bufOffset);
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ ReadOnlyMemory<char> first = buffer.First;
+ localInt ^= first.Length;
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ [InlineData(10_000, 100)]
+ private static void Char_Memory(int bufSize, int bufOffset)
+ {
+ var manager = new CustomMemoryForTest<char>(new char[bufSize], bufOffset, bufSize - 2 * bufOffset);
+ var buffer = new ReadOnlySequence<char>(manager.Memory);
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ ReadOnlyMemory<char> first = buffer.First;
+ localInt ^= first.Length;
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ [InlineData(10_000, 100)]
+ private static void Char_SingleSegment(int bufSize, int bufOffset)
+ {
+ var segment1 = new BufferSegment<char>(new char[bufSize]);
+ var buffer = new ReadOnlySequence<char>(segment1, bufOffset, segment1, bufSize - bufOffset);
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ ReadOnlyMemory<char> first = buffer.First;
+ localInt ^= first.Length;
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ [InlineData(10_000, 100)]
+ private static void Char_MultiSegment(int bufSize, int bufOffset)
+ {
+ var segment1 = new BufferSegment<char>(new char[bufSize / 10]);
+ BufferSegment<char> segment2 = segment1;
+ for (int j = 0; j < 10; j++)
+ segment2 = segment2.Append(new char[bufSize / 10]);
+
+ var buffer = new ReadOnlySequence<char>(segment1, bufOffset, segment2, bufSize / 10 - bufOffset);
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ ReadOnlyMemory<char> first = buffer.First;
+ localInt ^= first.Length;
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ [InlineData(10_000, 100)]
+ private static void String(int bufSize, int bufOffset)
+ {
+ ReadOnlyMemory<char> memory = new string('a', bufSize).AsMemory();
+ memory = memory.Slice(bufOffset, bufSize - 2 * bufOffset);
+ var buffer = new ReadOnlySequence<char>(memory);
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ ReadOnlyMemory<char> first = buffer.First;
+ localInt ^= first.Length;
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ private static void Char_Empty()
+ {
+ ReadOnlySequence<char> buffer = ReadOnlySequence<char>.Empty;
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ ReadOnlyMemory<char> first = buffer.First;
+ localInt ^= first.Length;
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ private static void Char_Default()
+ {
+ ReadOnlySequence<char> buffer = default;
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ ReadOnlyMemory<char> first = buffer.First;
+ localInt ^= first.Length;
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ }
+}
diff --git a/src/System.Memory/tests/Performance/Perf.ReadOnlySequence.GetPosition.cs b/src/System.Memory/tests/Performance/Perf.ReadOnlySequence.GetPosition.cs
new file mode 100644
index 0000000000..5a4c6721c2
--- /dev/null
+++ b/src/System.Memory/tests/Performance/Perf.ReadOnlySequence.GetPosition.cs
@@ -0,0 +1,215 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Memory.Tests;
+using Microsoft.Xunit.Performance;
+using Xunit;
+
+namespace System.Buffers.Tests
+{
+ public class Rerf_ReadOnlySequence_GetPosition
+ {
+ private const int InnerCount = 10_000;
+ volatile static int _volatileInt = 0;
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ [InlineData(10_000, 100)]
+ private static void Byte_Array(int bufSize, int bufOffset)
+ {
+ var buffer = new ReadOnlySequence<byte>(new byte[bufSize], bufOffset, bufSize - 2 * bufOffset);
+ int offset = (int)buffer.Length / 10;
+ SequencePosition end = buffer.GetPosition(0, buffer.End);
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ SequencePosition pos = buffer.Start;
+ while (pos != end)
+ {
+ pos = buffer.GetPosition(offset, pos);
+ localInt ^= pos.GetInteger();
+ }
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ [InlineData(10_000, 100)]
+ private static void Byte_MultiSegment(int bufSize, int bufOffset)
+ {
+ var segment1 = new BufferSegment<byte>(new byte[bufSize / 10]);
+ BufferSegment<byte> segment2 = segment1;
+ for (int j = 0; j < 10; j++)
+ segment2 = segment2.Append(new byte[bufSize / 10]);
+ var buffer = new ReadOnlySequence<byte>(segment1, bufOffset, segment2, bufSize / 10 - bufOffset);
+ int offset = (int)buffer.Length / 10;
+ SequencePosition end = buffer.GetPosition(0, buffer.End);
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ SequencePosition pos = buffer.Start;
+ while (pos != end)
+ {
+ pos = buffer.GetPosition(offset, pos);
+ localInt ^= pos.GetInteger();
+ }
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount * 10)]
+ private static void Byte_Empty()
+ {
+ ReadOnlySequence<byte> buffer = ReadOnlySequence<byte>.Empty;
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ SequencePosition pos = buffer.GetPosition(0);
+ localInt ^= pos.GetInteger();
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount * 10)]
+ private static void Byte_Default()
+ {
+ ReadOnlySequence<byte> buffer = default;
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ SequencePosition pos = buffer.GetPosition(0);
+ localInt ^= pos.GetInteger();
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ [InlineData(10_000, 100)]
+ private static void Char_MultiSegment(int bufSize, int bufOffset)
+ {
+ var segment1 = new BufferSegment<char>(new char[bufSize / 10]);
+ BufferSegment<char> segment2 = segment1;
+ for (int j = 0; j < 10; j++)
+ segment2 = segment2.Append(new char[bufSize / 10]);
+ var buffer = new ReadOnlySequence<char>(segment1, bufOffset, segment2, bufSize / 10 - bufOffset);
+ int offset = (int)buffer.Length / 10;
+ SequencePosition end = buffer.GetPosition(0, buffer.End);
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ SequencePosition pos = buffer.Start;
+ while (pos != end)
+ {
+ pos = buffer.GetPosition(offset, pos);
+ localInt ^= pos.GetInteger();
+ }
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ [InlineData(10_000, 100)]
+ private static void String(int bufSize, int bufOffset)
+ {
+ ReadOnlyMemory<char> memory = new string('a', bufSize).AsMemory();
+ memory = memory.Slice(bufOffset, bufSize - 2 * bufOffset);
+ var buffer = new ReadOnlySequence<char>(memory);
+ int offset = (int)buffer.Length / 10;
+ SequencePosition end = buffer.GetPosition(0, buffer.End);
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ SequencePosition pos = buffer.Start;
+ while (pos != end)
+ {
+ pos = buffer.GetPosition(offset, pos);
+ localInt ^= pos.GetInteger();
+ }
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount * 10)]
+ private static void Char_Empty()
+ {
+ ReadOnlySequence<char> buffer = ReadOnlySequence<char>.Empty;
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ SequencePosition p = buffer.GetPosition(0);
+ localInt ^= p.GetInteger();
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount * 10)]
+ private static void Char_Default()
+ {
+ ReadOnlySequence<char> buffer = default;
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ SequencePosition p = buffer.GetPosition(0);
+ localInt ^= p.GetInteger();
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ }
+}
diff --git a/src/System.Memory/tests/Performance/Perf.ReadOnlySequence.Slice.cs b/src/System.Memory/tests/Performance/Perf.ReadOnlySequence.Slice.cs
new file mode 100644
index 0000000000..6148c8a7cb
--- /dev/null
+++ b/src/System.Memory/tests/Performance/Perf.ReadOnlySequence.Slice.cs
@@ -0,0 +1,973 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Memory.Tests;
+using System.MemoryTests;
+using Microsoft.Xunit.Performance;
+using Xunit;
+
+namespace System.Buffers.Tests
+{
+ public class Perf_ReadOnlySequence_Slice
+ {
+ private const int InnerCount = 10_000;
+ volatile static int _volatileInt = 0;
+
+ #region Byte_Array
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ [InlineData(10_000, 100)]
+ private static void Byte_Array_Long(int bufSize, int bufOffset)
+ {
+ var buffer = new ReadOnlySequence<byte>(new byte[bufSize], bufOffset, bufSize - 2 * bufOffset);
+ long offset = buffer.Length / 10;
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ ReadOnlySequence<byte> sliced = buffer;
+ long sliceLen = sliced.Length;
+ while (sliceLen > 0)
+ {
+ sliceLen -= offset;
+ sliced = sliced.Slice(offset);
+ localInt ^= sliced.Start.GetInteger();
+ }
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ [InlineData(10_000, 100)]
+ private static void Byte_Array_LongLong(int bufSize, int bufOffset)
+ {
+ var buffer = new ReadOnlySequence<byte>(new byte[bufSize], bufOffset, bufSize - 2 * bufOffset);
+ long offset = buffer.Length / 20;
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ ReadOnlySequence<byte> sliced = buffer;
+ long sliceLen = sliced.Length;
+ while (sliceLen > 0)
+ {
+ sliceLen -= 2 * offset;
+ sliced = sliced.Slice(offset, sliceLen);
+ localInt ^= sliced.Start.GetInteger();
+ }
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ [InlineData(10_000, 100)]
+ private static void Byte_Array_LongPos(int bufSize, int bufOffset)
+ {
+ var buffer = new ReadOnlySequence<byte>(new byte[bufSize], bufOffset, bufSize - 2 * bufOffset);
+ long offset = buffer.Length / 20;
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ ReadOnlySequence<byte> sliced = buffer;
+ long sliceLen = sliced.Length;
+ SequencePosition end = sliced.GetPosition(0, sliced.End);
+ while (sliceLen > 0)
+ {
+ sliceLen -= 2 * offset;
+ end = new SequencePosition(end.GetObject(), end.GetInteger() - (int)offset);
+ sliced = sliced.Slice(offset, end);
+ localInt ^= sliced.Start.GetInteger();
+ }
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ [InlineData(10_000, 100)]
+ private static void Byte_Array_Pos(int bufSize, int bufOffset)
+ {
+ var buffer = new ReadOnlySequence<byte>(new byte[bufSize], bufOffset, bufSize - 2 * bufOffset);
+ long offset = buffer.Length / 10;
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ ReadOnlySequence<byte> sliced = buffer;
+ long sliceLen = sliced.Length;
+ SequencePosition start = sliced.GetPosition(0);
+ while (sliceLen > 0)
+ {
+ sliceLen -= offset;
+ start = new SequencePosition(start.GetObject(), start.GetInteger() + (int)offset);
+ sliced = sliced.Slice(start);
+ localInt ^= sliced.Start.GetInteger();
+ }
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ [InlineData(10_000, 100)]
+ private static void Byte_Array_PosLong(int bufSize, int bufOffset)
+ {
+ var buffer = new ReadOnlySequence<byte>(new byte[bufSize], bufOffset, bufSize - 2 * bufOffset);
+ long offset = buffer.Length / 20;
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ ReadOnlySequence<byte> sliced = buffer;
+ long sliceLen = sliced.Length;
+ SequencePosition start = sliced.GetPosition(0);
+ while (sliceLen > 0)
+ {
+ sliceLen -= 2 * offset;
+ start = new SequencePosition(start.GetObject(), start.GetInteger() + (int)offset);
+ sliced = sliced.Slice(start, sliceLen);
+ localInt ^= sliced.Start.GetInteger();
+ }
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ [InlineData(10_000, 100)]
+ private static void Byte_Array_PosPos(int bufSize, int bufOffset)
+ {
+ var buffer = new ReadOnlySequence<byte>(new byte[bufSize], bufOffset, bufSize - 2 * bufOffset);
+ long offset = buffer.Length / 20;
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ ReadOnlySequence<byte> sliced = buffer;
+ long sliceLen = sliced.Length;
+ SequencePosition start = sliced.GetPosition(0);
+ SequencePosition end = sliced.GetPosition(0, sliced.End);
+ while (sliceLen > 0)
+ {
+ sliceLen -= 2 * offset;
+ start = new SequencePosition(start.GetObject(), start.GetInteger() + (int)offset);
+ end = new SequencePosition(end.GetObject(), end.GetInteger() - (int)offset);
+ sliced = sliced.Slice(start, end);
+ localInt ^= sliced.Start.GetInteger();
+ }
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ #endregion
+
+ #region Byte_Memory
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ [InlineData(10_000, 100)]
+ private static void Byte_Memory_Long(int bufSize, int bufOffset)
+ {
+ var manager = new CustomMemoryForTest<byte>(new byte[bufSize], bufOffset, bufSize - 2 * bufOffset);
+ var buffer = new ReadOnlySequence<byte>(manager.Memory);
+ long offset = buffer.Length / 10;
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ ReadOnlySequence<byte> sliced = buffer;
+ long sliceLen = sliced.Length;
+ while (sliceLen > 0)
+ {
+ sliceLen -= offset;
+ sliced = sliced.Slice(offset);
+ localInt ^= sliced.Start.GetInteger();
+ }
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ [InlineData(10_000, 100)]
+ private static void Byte_Memory_LongLong(int bufSize, int bufOffset)
+ {
+ var manager = new CustomMemoryForTest<byte>(new byte[bufSize], bufOffset, bufSize - 2 * bufOffset);
+ var buffer = new ReadOnlySequence<byte>(manager.Memory);
+ long offset = buffer.Length / 20;
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ ReadOnlySequence<byte> sliced = buffer;
+ long sliceLen = sliced.Length;
+ while (sliceLen > 0)
+ {
+ sliceLen -= 2 * offset;
+ sliced = sliced.Slice(offset, sliceLen);
+ localInt ^= sliced.Start.GetInteger();
+ }
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ [InlineData(10_000, 100)]
+ private static void Byte_Memory_LongPos(int bufSize, int bufOffset)
+ {
+ var manager = new CustomMemoryForTest<byte>(new byte[bufSize], bufOffset, bufSize - 2 * bufOffset);
+ var buffer = new ReadOnlySequence<byte>(manager.Memory);
+ long offset = buffer.Length / 20;
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ ReadOnlySequence<byte> sliced = buffer;
+ long sliceLen = sliced.Length;
+ SequencePosition end = sliced.GetPosition(0, sliced.End);
+ while (sliceLen > 0)
+ {
+ sliceLen -= 2 * offset;
+ end = new SequencePosition(end.GetObject(), end.GetInteger() - (int)offset);
+ sliced = sliced.Slice(offset, end);
+ localInt ^= sliced.Start.GetInteger();
+ }
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ [InlineData(10_000, 100)]
+ private static void Byte_Memory_Pos(int bufSize, int bufOffset)
+ {
+ var manager = new CustomMemoryForTest<byte>(new byte[bufSize], bufOffset, bufSize - 2 * bufOffset);
+ var buffer = new ReadOnlySequence<byte>(manager.Memory);
+ long offset = buffer.Length / 10;
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ ReadOnlySequence<byte> sliced = buffer;
+ long sliceLen = sliced.Length;
+ SequencePosition start = sliced.GetPosition(0);
+ while (sliceLen > 0)
+ {
+ sliceLen -= offset;
+ start = new SequencePosition(start.GetObject(), start.GetInteger() + (int)offset);
+ sliced = sliced.Slice(start);
+ localInt ^= sliced.Start.GetInteger();
+ }
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ [InlineData(10_000, 100)]
+ private static void Byte_Memory_PosLong(int bufSize, int bufOffset)
+ {
+ var manager = new CustomMemoryForTest<byte>(new byte[bufSize], bufOffset, bufSize - 2 * bufOffset);
+ var buffer = new ReadOnlySequence<byte>(manager.Memory);
+ long offset = buffer.Length / 20;
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ ReadOnlySequence<byte> sliced = buffer;
+ long sliceLen = sliced.Length;
+ SequencePosition start = sliced.GetPosition(0);
+ while (sliceLen > 0)
+ {
+ sliceLen -= 2 * offset;
+ start = new SequencePosition(start.GetObject(), start.GetInteger() + (int)offset);
+ sliced = sliced.Slice(start, sliceLen);
+ localInt ^= sliced.Start.GetInteger();
+ }
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ [InlineData(10_000, 100)]
+ private static void Byte_Memory_PosPos(int bufSize, int bufOffset)
+ {
+ var manager = new CustomMemoryForTest<byte>(new byte[bufSize], bufOffset, bufSize - 2 * bufOffset);
+ var buffer = new ReadOnlySequence<byte>(manager.Memory);
+ long offset = buffer.Length / 20;
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ ReadOnlySequence<byte> sliced = buffer;
+ long sliceLen = sliced.Length;
+ SequencePosition start = sliced.GetPosition(0);
+ SequencePosition end = sliced.GetPosition(0, sliced.End);
+ while (sliceLen > 0)
+ {
+ sliceLen -= 2 * offset;
+ start = new SequencePosition(start.GetObject(), start.GetInteger() + (int)offset);
+ end = new SequencePosition(end.GetObject(), end.GetInteger() - (int)offset);
+ sliced = sliced.Slice(start, end);
+ localInt ^= sliced.Start.GetInteger();
+ }
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ #endregion
+
+ #region Byte_SingleSegment
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ [InlineData(10_000, 100)]
+ private static void Byte_SingleSegment_Long(int bufSize, int bufOffset)
+ {
+ var segment1 = new BufferSegment<byte>(new byte[bufSize]);
+ var buffer = new ReadOnlySequence<byte>(segment1, bufOffset, segment1, bufSize - bufOffset);
+ long offset = buffer.Length / 10;
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ ReadOnlySequence<byte> sliced = buffer;
+ long sliceLen = sliced.Length;
+ while (sliceLen > 0)
+ {
+ sliceLen -= offset;
+ sliced = sliced.Slice(offset);
+ localInt ^= sliced.Start.GetInteger();
+ }
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ [InlineData(10_000, 100)]
+ private static void Byte_SingleSegment_LongLong(int bufSize, int bufOffset)
+ {
+ var segment1 = new BufferSegment<byte>(new byte[bufSize]);
+ var buffer = new ReadOnlySequence<byte>(segment1, bufOffset, segment1, bufSize - bufOffset);
+ long offset = buffer.Length / 20;
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ ReadOnlySequence<byte> sliced = buffer;
+ long sliceLen = sliced.Length;
+ while (sliceLen > 0)
+ {
+ sliceLen -= 2 * offset;
+ sliced = sliced.Slice(offset, sliceLen);
+ localInt ^= sliced.Start.GetInteger();
+ }
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ [InlineData(10_000, 100)]
+ private static void Byte_SingleSegment_LongPos(int bufSize, int bufOffset)
+ {
+ var segment1 = new BufferSegment<byte>(new byte[bufSize]);
+ var buffer = new ReadOnlySequence<byte>(segment1, bufOffset, segment1, bufSize - bufOffset);
+ long offset = buffer.Length / 20;
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ ReadOnlySequence<byte> sliced = buffer;
+ long sliceLen = sliced.Length;
+ SequencePosition end = sliced.GetPosition(0, sliced.End);
+ while (sliceLen > 0)
+ {
+ sliceLen -= 2 * offset;
+ end = new SequencePosition(end.GetObject(), end.GetInteger() - (int)offset);
+ sliced = sliced.Slice(offset, end);
+ localInt ^= sliced.Start.GetInteger();
+ }
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ [InlineData(10_000, 100)]
+ private static void Byte_SingleSegment_Pos(int bufSize, int bufOffset)
+ {
+ var segment1 = new BufferSegment<byte>(new byte[bufSize]);
+ var buffer = new ReadOnlySequence<byte>(segment1, bufOffset, segment1, bufSize - bufOffset);
+ long offset = buffer.Length / 10;
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ ReadOnlySequence<byte> sliced = buffer;
+ long sliceLen = sliced.Length;
+ SequencePosition start = sliced.GetPosition(0);
+ while (sliceLen > 0)
+ {
+ sliceLen -= offset;
+ start = new SequencePosition(start.GetObject(), start.GetInteger() + (int)offset);
+ sliced = sliced.Slice(start);
+ localInt ^= sliced.Start.GetInteger();
+ }
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ [InlineData(10_000, 100)]
+ private static void Byte_SingleSegment_PosLong(int bufSize, int bufOffset)
+ {
+ var segment1 = new BufferSegment<byte>(new byte[bufSize]);
+ var buffer = new ReadOnlySequence<byte>(segment1, bufOffset, segment1, bufSize - bufOffset);
+ long offset = buffer.Length / 20;
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ ReadOnlySequence<byte> sliced = buffer;
+ long sliceLen = sliced.Length;
+ SequencePosition start = sliced.GetPosition(0);
+ while (sliceLen > 0)
+ {
+ sliceLen -= 2 * offset;
+ start = new SequencePosition(start.GetObject(), start.GetInteger() + (int)offset);
+ sliced = sliced.Slice(start, sliceLen);
+ localInt ^= sliced.Start.GetInteger();
+ }
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ [InlineData(10_000, 100)]
+ private static void Byte_SingleSegment_PosPos(int bufSize, int bufOffset)
+ {
+ var segment1 = new BufferSegment<byte>(new byte[bufSize]);
+ var buffer = new ReadOnlySequence<byte>(segment1, bufOffset, segment1, bufSize - bufOffset);
+ long offset = buffer.Length / 20;
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ ReadOnlySequence<byte> sliced = buffer;
+ long sliceLen = sliced.Length;
+ SequencePosition start = sliced.GetPosition(0);
+ SequencePosition end = sliced.GetPosition(0, sliced.End);
+ while (sliceLen > 0)
+ {
+ sliceLen -= 2 * offset;
+ start = new SequencePosition(start.GetObject(), start.GetInteger() + (int)offset);
+ end = new SequencePosition(end.GetObject(), end.GetInteger() - (int)offset);
+ sliced = sliced.Slice(start, end);
+ localInt ^= sliced.Start.GetInteger();
+ }
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ #endregion
+
+ #region Byte_MultiSegment
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ [InlineData(10_000, 100)]
+ private static void Byte_MultiSegment_Long(int bufSize, int bufOffset)
+ {
+ var segment1 = new BufferSegment<byte>(new byte[bufSize / 10]);
+ BufferSegment<byte> segment2 = segment1;
+ for (int j = 0; j < 10; j++)
+ segment2 = segment2.Append(new byte[bufSize / 10]);
+ var buffer = new ReadOnlySequence<byte>(segment1, bufOffset, segment2, bufSize / 10 - bufOffset);
+ long offset = buffer.Length / 10;
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ ReadOnlySequence<byte> sliced = buffer;
+ long sliceLen = sliced.Length;
+ while (sliceLen > 0)
+ {
+ sliceLen -= offset;
+ sliced = sliced.Slice(offset);
+ localInt ^= sliced.Start.GetInteger();
+ }
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ [InlineData(10_000, 100)]
+ private static void Byte_MultiSegment_LongLong(int bufSize, int bufOffset)
+ {
+ var segment1 = new BufferSegment<byte>(new byte[bufSize / 10]);
+ BufferSegment<byte> segment2 = segment1;
+ for (int j = 0; j < 10; j++)
+ segment2 = segment2.Append(new byte[bufSize / 10]);
+ var buffer = new ReadOnlySequence<byte>(segment1, bufOffset, segment2, bufSize / 10 - bufOffset);
+ long offset = buffer.Length / 20;
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ ReadOnlySequence<byte> sliced = buffer;
+ long sliceLen = sliced.Length;
+ while (sliceLen > 0)
+ {
+ sliceLen -= 2 * offset;
+ sliced = sliced.Slice(offset, sliceLen);
+ localInt ^= sliced.Start.GetInteger();
+ }
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ [InlineData(10_000, 100)]
+ private static void Byte_MultiSegment_LongPos(int bufSize, int bufOffset)
+ {
+ var segment1 = new BufferSegment<byte>(new byte[bufSize / 10]);
+ BufferSegment<byte> segment2 = segment1;
+ for (int j = 0; j < 10; j++)
+ segment2 = segment2.Append(new byte[bufSize / 10]);
+ var buffer = new ReadOnlySequence<byte>(segment1, bufOffset, segment2, bufSize / 10 - bufOffset);
+ long offset = buffer.Length / 20;
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ ReadOnlySequence<byte> sliced = buffer;
+ long sliceLen = sliced.Length;
+ while (sliceLen > 0)
+ {
+ sliceLen -= offset;
+ SequencePosition end = sliced.GetPosition(sliceLen);
+ sliceLen -= offset;
+ sliced = sliced.Slice(offset, end);
+ localInt ^= sliced.Start.GetInteger();
+ }
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ [InlineData(10_000, 100)]
+ private static void Byte_MultiSegment_Pos(int bufSize, int bufOffset)
+ {
+ var segment1 = new BufferSegment<byte>(new byte[bufSize / 10]);
+ BufferSegment<byte> segment2 = segment1;
+ for (int j = 0; j < 10; j++)
+ segment2 = segment2.Append(new byte[bufSize / 10]);
+ var buffer = new ReadOnlySequence<byte>(segment1, bufOffset, segment2, bufSize / 10 - bufOffset);
+ long offset = buffer.Length / 10;
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ ReadOnlySequence<byte> sliced = buffer;
+ long sliceLen = sliced.Length;
+ while (sliceLen > 0)
+ {
+ sliceLen -= offset;
+ SequencePosition start = sliced.GetPosition(offset);
+ sliced = sliced.Slice(start);
+ localInt ^= sliced.Start.GetInteger();
+ }
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ [InlineData(10_000, 100)]
+ private static void Byte_MultiSegment_PosLong(int bufSize, int bufOffset)
+ {
+ var segment1 = new BufferSegment<byte>(new byte[bufSize / 10]);
+ BufferSegment<byte> segment2 = segment1;
+ for (int j = 0; j < 10; j++)
+ segment2 = segment2.Append(new byte[bufSize / 10]);
+ var buffer = new ReadOnlySequence<byte>(segment1, bufOffset, segment2, bufSize / 10 - bufOffset);
+ long offset = buffer.Length / 20;
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ ReadOnlySequence<byte> sliced = buffer;
+ long sliceLen = sliced.Length;
+ while (sliceLen > 0)
+ {
+ sliceLen -= 2 * offset;
+ SequencePosition start = sliced.GetPosition(offset);
+ sliced = sliced.Slice(start, sliceLen);
+ localInt ^= sliced.Start.GetInteger();
+ }
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ [InlineData(10_000, 100)]
+ private static void Byte_MultiSegment_PosPos(int bufSize, int bufOffset)
+ {
+ var segment1 = new BufferSegment<byte>(new byte[bufSize / 10]);
+ BufferSegment<byte> segment2 = segment1;
+ for (int j = 0; j < 10; j++)
+ segment2 = segment2.Append(new byte[bufSize / 10]);
+ var buffer = new ReadOnlySequence<byte>(segment1, bufOffset, segment2, bufSize / 10 - bufOffset);
+ long offset = buffer.Length / 20;
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ ReadOnlySequence<byte> sliced = buffer;
+ long sliceLen = sliced.Length;
+ while (sliceLen > 0)
+ {
+ sliceLen -= offset;
+ SequencePosition end = sliced.GetPosition(sliceLen);
+ SequencePosition start = sliced.GetPosition(offset);
+ sliceLen -= offset;
+ sliced = sliced.Slice(start, end);
+ localInt ^= sliced.Start.GetInteger();
+ }
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ #endregion
+
+ #region String
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ [InlineData(10_000, 100)]
+ private static void String_Long(int bufSize, int bufOffset)
+ {
+ ReadOnlyMemory<char> memory = new string('a', bufSize).AsMemory();
+ memory = memory.Slice(bufOffset, bufSize - 2 * bufOffset);
+ var buffer = new ReadOnlySequence<char>(memory);
+ long offset = buffer.Length / 10;
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ ReadOnlySequence<char> sliced = buffer;
+ long sliceLen = sliced.Length;
+ while (sliceLen > 0)
+ {
+ sliceLen -= offset;
+ sliced = sliced.Slice(offset);
+ localInt ^= sliced.Start.GetInteger();
+ }
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ [InlineData(10_000, 100)]
+ private static void String_LongLong(int bufSize, int bufOffset)
+ {
+ ReadOnlyMemory<char> memory = new string('a', bufSize).AsMemory();
+ memory = memory.Slice(bufOffset, bufSize - 2 * bufOffset);
+ var buffer = new ReadOnlySequence<char>(memory);
+ long offset = buffer.Length / 20;
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ ReadOnlySequence<char> sliced = buffer;
+ long sliceLen = sliced.Length;
+ while (sliceLen > 0)
+ {
+ sliceLen -= 2 * offset;
+ sliced = sliced.Slice(offset, sliceLen);
+ localInt ^= sliced.Start.GetInteger();
+ }
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ [InlineData(10_000, 100)]
+ private static void String_LongPos(int bufSize, int bufOffset)
+ {
+ ReadOnlyMemory<char> memory = new string('a', bufSize).AsMemory();
+ memory = memory.Slice(bufOffset, bufSize - 2 * bufOffset);
+ var buffer = new ReadOnlySequence<char>(memory);
+ long offset = buffer.Length / 20;
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ ReadOnlySequence<char> sliced = buffer;
+ long sliceLen = sliced.Length;
+ SequencePosition end = sliced.GetPosition(0, sliced.End);
+ while (sliceLen > 0)
+ {
+ sliceLen -= 2 * offset;
+ end = new SequencePosition(end.GetObject(), end.GetInteger() - (int)offset);
+ sliced = sliced.Slice(offset, end);
+ localInt ^= sliced.Start.GetInteger();
+ }
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ [InlineData(10_000, 100)]
+ private static void String_Pos(int bufSize, int bufOffset)
+ {
+ ReadOnlyMemory<char> memory = new string('a', bufSize).AsMemory();
+ memory = memory.Slice(bufOffset, bufSize - 2 * bufOffset);
+ var buffer = new ReadOnlySequence<char>(memory);
+ long offset = buffer.Length / 10;
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ ReadOnlySequence<char> sliced = buffer;
+ long sliceLen = sliced.Length;
+ SequencePosition start = sliced.GetPosition(0);
+ while (sliceLen > 0)
+ {
+ sliceLen -= offset;
+ start = new SequencePosition(start.GetObject(), start.GetInteger() + (int)offset);
+ sliced = sliced.Slice(start);
+ localInt ^= sliced.Start.GetInteger();
+ }
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ [InlineData(10_000, 100)]
+ private static void String_PosLong(int bufSize, int bufOffset)
+ {
+ ReadOnlyMemory<char> memory = new string('a', bufSize).AsMemory();
+ memory = memory.Slice(bufOffset, bufSize - 2 * bufOffset);
+ var buffer = new ReadOnlySequence<char>(memory);
+ long offset = buffer.Length / 20;
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ ReadOnlySequence<char> sliced = buffer;
+ long sliceLen = sliced.Length;
+ SequencePosition start = sliced.GetPosition(0);
+ while (sliceLen > 0)
+ {
+ sliceLen -= 2 * offset;
+ start = new SequencePosition(start.GetObject(), start.GetInteger() + (int)offset);
+ sliced = sliced.Slice(start, sliceLen);
+ localInt ^= sliced.Start.GetInteger();
+ }
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ [InlineData(10_000, 100)]
+ private static void String_PosPos(int bufSize, int bufOffset)
+ {
+ ReadOnlyMemory<char> memory = new string('a', bufSize).AsMemory();
+ memory = memory.Slice(bufOffset, bufSize - 2 * bufOffset);
+ var buffer = new ReadOnlySequence<char>(memory);
+ long offset = buffer.Length / 20;
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ ReadOnlySequence<char> sliced = buffer;
+ long sliceLen = sliced.Length;
+ SequencePosition start = sliced.GetPosition(0);
+ SequencePosition end = sliced.GetPosition(0, sliced.End);
+ while (sliceLen > 0)
+ {
+ sliceLen -= 2 * offset;
+ start = new SequencePosition(start.GetObject(), start.GetInteger() + (int)offset);
+ end = new SequencePosition(end.GetObject(), end.GetInteger() - (int)offset);
+ sliced = sliced.Slice(start, end);
+ localInt ^= sliced.Start.GetInteger();
+ }
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ #endregion
+
+ }
+}
diff --git a/src/System.Memory/tests/Performance/Perf.ReadOnlySequence.TryGet.cs b/src/System.Memory/tests/Performance/Perf.ReadOnlySequence.TryGet.cs
new file mode 100644
index 0000000000..2d761181f9
--- /dev/null
+++ b/src/System.Memory/tests/Performance/Perf.ReadOnlySequence.TryGet.cs
@@ -0,0 +1,314 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Memory.Tests;
+using System.MemoryTests;
+using Microsoft.Xunit.Performance;
+using Xunit;
+
+namespace System.Buffers.Tests
+{
+ public class Perf_ReadOnlySequence_TryGet
+ {
+ private const int InnerCount = 100_000;
+ volatile static int _volatileInt = 0;
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ [InlineData(10_000, 100)]
+ private static void Byte_Array(int bufSize, int bufOffset)
+ {
+ var buffer = new ReadOnlySequence<byte>(new byte[bufSize], bufOffset, bufSize - 2 * bufOffset);
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ SequencePosition p = buffer.Start;
+ while (buffer.TryGet(ref p, out ReadOnlyMemory<byte> memory))
+ localInt ^= memory.Length;
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ [InlineData(10_000, 100)]
+ private static void Byte_Memory(int bufSize, int bufOffset)
+ {
+ var manager = new CustomMemoryForTest<byte>(new byte[bufSize], bufOffset, bufSize - 2 * bufOffset);
+ var buffer = new ReadOnlySequence<byte>(manager.Memory);
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ SequencePosition p = buffer.Start;
+ while (buffer.TryGet(ref p, out ReadOnlyMemory<byte> memory))
+ localInt ^= memory.Length;
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ [InlineData(10_000, 100)]
+ private static void Byte_SingleSegment(int bufSize, int bufOffset)
+ {
+ var segment1 = new BufferSegment<byte>(new byte[bufSize]);
+ var buffer = new ReadOnlySequence<byte>(segment1, bufOffset, segment1, bufSize - bufOffset);
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ SequencePosition p = buffer.Start;
+ while (buffer.TryGet(ref p, out ReadOnlyMemory<byte> memory))
+ localInt ^= memory.Length;
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount / 10)]
+ [InlineData(10_000, 100)]
+ private static void Byte_MultiSegment(int bufSize, int bufOffset)
+ {
+ var segment1 = new BufferSegment<byte>(new byte[bufSize / 10]);
+ BufferSegment<byte> segment2 = segment1;
+ for (int j = 0; j < 10; j++)
+ segment2 = segment2.Append(new byte[bufSize / 10]);
+ var buffer = new ReadOnlySequence<byte>(segment1, bufOffset, segment2, bufSize / 10 - bufOffset);
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ SequencePosition p = buffer.Start;
+ while (buffer.TryGet(ref p, out ReadOnlyMemory<byte> memory))
+ localInt ^= memory.Length;
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ private static void Byte_Empty()
+ {
+ ReadOnlySequence<byte> buffer = ReadOnlySequence<byte>.Empty;
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ SequencePosition p = buffer.Start;
+ while (buffer.TryGet(ref p, out ReadOnlyMemory<byte> memory))
+ localInt ^= memory.Length;
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ private static void Byte_Default()
+ {
+ ReadOnlySequence<byte> buffer = default;
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ SequencePosition p = buffer.Start;
+ while (buffer.TryGet(ref p, out ReadOnlyMemory<byte> memory))
+ localInt ^= memory.Length;
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ [InlineData(10_000, 100)]
+ private static void Char_Array(int bufSize, int bufOffset)
+ {
+ var buffer = new ReadOnlySequence<char>(new char[bufSize], bufOffset, bufSize - 2 * bufOffset);
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ SequencePosition p = buffer.Start;
+ while (buffer.TryGet(ref p, out ReadOnlyMemory<char> memory))
+ localInt ^= memory.Length;
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ [InlineData(10_000, 100)]
+ private static void Char_Memory(int bufSize, int bufOffset)
+ {
+ var manager = new CustomMemoryForTest<char>(new char[bufSize], bufOffset, bufSize - 2 * bufOffset);
+ var buffer = new ReadOnlySequence<char>(manager.Memory);
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ SequencePosition p = buffer.Start;
+ while (buffer.TryGet(ref p, out ReadOnlyMemory<char> memory))
+ localInt ^= memory.Length;
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ [InlineData(10_000, 100)]
+ private static void Char_SingleSegment(int bufSize, int bufOffset)
+ {
+ var segment1 = new BufferSegment<char>(new char[bufSize]);
+ var buffer = new ReadOnlySequence<char>(segment1, bufOffset, segment1, bufSize - bufOffset);
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ SequencePosition p = buffer.Start;
+ while (buffer.TryGet(ref p, out ReadOnlyMemory<char> memory))
+ localInt ^= memory.Length;
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount / 10)]
+ [InlineData(10_000, 100)]
+ private static void Char_MultiSegment(int bufSize, int bufOffset)
+ {
+ var segment1 = new BufferSegment<char>(new char[bufSize / 10]);
+ BufferSegment<char> segment2 = segment1;
+ for (int j = 0; j < 10; j++)
+ segment2 = segment2.Append(new char[bufSize / 10]);
+ var buffer = new ReadOnlySequence<char>(segment1, bufOffset, segment2, bufSize / 10 - bufOffset);
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ SequencePosition p = buffer.Start;
+ while (buffer.TryGet(ref p, out ReadOnlyMemory<char> memory))
+ localInt ^= memory.Length;
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ [InlineData(10_000, 100)]
+ private static void String(int bufSize, int bufOffset)
+ {
+ ReadOnlyMemory<char> strMemory = new string('a', bufSize).AsMemory();
+ strMemory = strMemory.Slice(bufOffset, bufSize - bufOffset);
+ var buffer = new ReadOnlySequence<char>(strMemory);
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ SequencePosition p = buffer.Start;
+ while (buffer.TryGet(ref p, out ReadOnlyMemory<char> memory))
+ localInt ^= memory.Length;
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ private static void Char_Empty()
+ {
+ ReadOnlySequence<char> buffer = ReadOnlySequence<char>.Empty;
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ SequencePosition p = buffer.Start;
+ while (buffer.TryGet(ref p, out ReadOnlyMemory<char> memory))
+ localInt ^= memory.Length;
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ [Benchmark(InnerIterationCount = InnerCount)]
+ private static void Char_Default()
+ {
+ ReadOnlySequence<char> buffer = default;
+
+ foreach (BenchmarkIteration iteration in Benchmark.Iterations)
+ {
+ int localInt = 0;
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Benchmark.InnerIterationCount; i++)
+ {
+ SequencePosition p = buffer.Start;
+ while (buffer.TryGet(ref p, out ReadOnlyMemory<char> memory))
+ localInt ^= memory.Length;
+ }
+ }
+ _volatileInt = localInt;
+ }
+ }
+
+ }
+}
diff --git a/src/System.Memory/tests/Performance/System.Memory.Performance.Tests.csproj b/src/System.Memory/tests/Performance/System.Memory.Performance.Tests.csproj
index 692fb4e62b..edb6ffe73c 100644
--- a/src/System.Memory/tests/Performance/System.Memory.Performance.Tests.csproj
+++ b/src/System.Memory/tests/Performance/System.Memory.Performance.Tests.csproj
@@ -10,6 +10,11 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Release|AnyCPU'" />
<ItemGroup>
<Compile Include="Perf.Base64EncodeDecode.cs" />
+ <Compile Include="Perf.ReadOnlySequence.Enumerator.cs" />
+ <Compile Include="Perf.ReadOnlySequence.First.cs" />
+ <Compile Include="Perf.ReadOnlySequence.GetPosition.cs" />
+ <Compile Include="Perf.ReadOnlySequence.Slice.cs" />
+ <Compile Include="Perf.ReadOnlySequence.TryGet.cs" />
<Compile Include="Perf.Span.BinaryReadAndWrite.cs" />
<Compile Include="Perf.Span.BinarySearch.cs" />
<Compile Include="Perf.Span.Clear.cs" />
@@ -26,6 +31,12 @@
<Compile Include="$(CommonTestPath)\System\PerfUtils.cs">
<Link>Common\System\PerfUtils.cs</Link>
</Compile>
+ <Compile Include="..\Memory\CustomMemoryForTest.cs">
+ <Link>Common\System\MemoryTests\CustomMemoryForTest.cs</Link>
+ </Compile>
+ <Compile Include="..\ReadOnlyBuffer\BufferSegment.cs">
+ <Link>Common\System\Memory\Tests\BufferSegment.cs</Link>
+ </Compile>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="$(CommonPath)\..\perf\PerfRunner\PerfRunner.csproj">