Skip to content

Instantly share code, notes, and snippets.

@mgravell
Last active March 2, 2023 13:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mgravell/942f5addefb83004ec185eca078d0865 to your computer and use it in GitHub Desktop.
Save mgravell/942f5addefb83004ec185eca078d0865 to your computer and use it in GitHub Desktop.
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Jobs;
using BenchmarkDotNet.Running;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
namespace SequenceReaderBenchmarks;
static class Program {
static void Main(string[] args) {
// perform validations
var obj = new SequenceReaderBenchmark();
obj.SegmentLength = 4;
obj.Init();
obj.SegmentLength = 1024;
obj.Init();
obj.SegmentLength = -1024;
obj.Init();
// bench
BenchmarkRunner.Run<SequenceReaderBenchmark>(args: args);
}
}
[SimpleJob(RuntimeMoniker.Net60), SimpleJob(RuntimeMoniker.Net70)]
public class SequenceReaderBenchmark {
private const int TotalLength = 1024;
[Params(4, 128, 1024, -1024)]
public int SegmentLength { get; set; }
private System.Buffers.ReadOnlySequence<int> payload;
[Benchmark]
public int SystemTryRead() {
var reader = new System.Buffers.SequenceReader<int>(payload);
int count = 0;
while (reader.TryRead(out _)) {
count++;
}
return count;
}
[Benchmark]
public int CustomTryRead() {
var reader = new System.Buffers2.SequenceReader<int>(payload);
int count = 0;
while (reader.TryRead(out _)) {
count++;
}
return count;
}
[Benchmark]
public int SystemTryPeek() {
var reader = new System.Buffers.SequenceReader<int>(payload);
int count = 0; // doesn't advance, so: loop
for (int i = 0; i < TotalLength && reader.TryPeek(out _); i++) {
count++;
}
return count;
}
[Benchmark]
public int CustomTryPeek() {
var reader = new System.Buffers2.SequenceReader<int>(payload);
int count = 0; // doesn't advance, so: loop
for (int i = 0; i < TotalLength && reader.TryPeek(out _); i++) {
count++;
}
return count;
}
[Benchmark]
public long SystemAdvancePastAny() {
var reader = new System.Buffers.SequenceReader<int>(payload);
return reader.AdvancePastAny(0, 0, 0);
}
[Benchmark]
public long CustomAdvancePastAny() {
var reader = new System.Buffers2.SequenceReader<int>(payload);
return reader.AdvancePastAny(0, 0, 0);
}
[DoesNotReturn]
static void Throw() => throw new InvalidOperationException();
[GlobalSetup]
public void Init() {
if (SegmentLength < 0) {
payload = new System.Buffers.ReadOnlySequence<int>(new int[TotalLength]);
}
else {
Segment first = new(SegmentLength, null), last = first;
int remaining = TotalLength - SegmentLength;
while (remaining != 0) {
var len = Math.Min(remaining, SegmentLength);
last = new Segment(len, last);
remaining -= len;
}
payload = new System.Buffers.ReadOnlySequence<int>(first, 0, last, last.Memory.Length);
}
if (payload.Length != TotalLength) Throw();
if (SystemTryRead() != TotalLength) Throw();
if (CustomTryRead() != TotalLength) Throw();
if (SystemTryPeek() != TotalLength) Throw();
if (CustomTryPeek() != TotalLength) Throw();
if (SystemAdvancePastAny() != TotalLength) Throw();
if (CustomAdvancePastAny() != TotalLength) Throw();
}
sealed class Segment : System.Buffers.ReadOnlySequenceSegment<int>
{
public Segment(int length, Segment? previous) {
Memory = new int[length];
if (previous is null) {
RunningIndex = 0;
}
else {
RunningIndex = previous.RunningIndex + previous.Memory.Length;
previous.Next = this;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment