Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save aalmada/cc63f4e791affa6e23a300e820bc6567 to your computer and use it in GitHub Desktop.
Save aalmada/cc63f4e791affa6e23a300e820bc6567 to your computer and use it in GitHub Desktop.
BenchmarkDotNet=v0.11.4, OS=macOS Mojave 10.14.4 (18E226) [Darwin 18.5.0]
Intel Core i5-7360U CPU 2.30GHz (Kaby Lake), 1 CPU, 4 logical and 2 physical cores
.NET Core SDK=3.0.100-preview4-011223
  [Host]     : .NET Core 2.1.6 (CoreCLR 4.6.27019.06, CoreFX 4.6.27019.05), 64bit RyuJIT
  DefaultJob : .NET Core 2.1.6 (CoreCLR 4.6.27019.06, CoreFX 4.6.27019.05), 64bit RyuJIT

Method Categories Count Mean Error StdDev Median Ratio RatioSD Gen 0/1k Op Gen 1/1k Op Gen 2/1k Op Allocated Memory/Op
Enumerator Count 0 8.622 ns 0.2957 ns 0.8672 ns 8.635 ns 1.00 0.00 0.0114 - - 24 B
MyEnumerator Count 0 7.793 ns 0.2514 ns 0.7413 ns 7.805 ns 0.91 0.13 0.0114 - - 24 B
BenValueEnumerator Count 0 7.709 ns 0.1399 ns 0.1241 ns 7.693 ns 0.85 0.08 - - - -
MyValueEnumerator Count 0 7.688 ns 0.1077 ns 0.1008 ns 7.649 ns 0.84 0.08 - - - -
Enumerator_Predicate Count_Predicate 0 9.998 ns 0.2811 ns 0.8245 ns 9.738 ns 1.00 0.00 0.0114 - - 24 B
MyEnumerator_Predicate Count_Predicate 0 9.739 ns 0.2365 ns 0.6861 ns 9.542 ns 0.98 0.09 0.0114 - - 24 B
BenValueEnumerator_Predicate Count_Predicate 0 11.800 ns 0.2518 ns 0.2355 ns 11.777 ns 1.18 0.07 - - - -
MyValueEnumerator_Predicate Count_Predicate 0 9.809 ns 0.2284 ns 0.2346 ns 9.836 ns 0.98 0.07 - - - -
Enumerator Count 1000 317.097 ns 6.1965 ns 8.2721 ns 315.968 ns 1.00 0.00 0.0110 - - 24 B
MyEnumerator Count 1000 317.963 ns 5.7048 ns 6.1041 ns 318.249 ns 1.00 0.04 0.0110 - - 24 B
BenValueEnumerator Count 1000 1,531.703 ns 14.5722 ns 13.6309 ns 1,524.631 ns 4.85 0.13 - - - -
MyValueEnumerator Count 1000 1,543.778 ns 30.5211 ns 29.9758 ns 1,529.392 ns 4.88 0.18 - - - -
Enumerator_Predicate Count_Predicate 1000 2,037.564 ns 39.4347 ns 45.4130 ns 2,023.135 ns 1.00 0.00 0.0076 - - 24 B
MyEnumerator_Predicate Count_Predicate 1000 2,046.857 ns 40.5158 ns 45.0332 ns 2,039.495 ns 1.00 0.04 0.0076 - - 24 B
BenValueEnumerator_Predicate Count_Predicate 1000 2,868.858 ns 54.9236 ns 53.9424 ns 2,850.419 ns 1.40 0.04 - - - -
MyValueEnumerator_Predicate Count_Predicate 1000 2,613.342 ns 51.9586 ns 51.0303 ns 2,601.950 ns 1.28 0.04 - - - -
Enumerator Count 100000 29,101.793 ns 569.3419 ns 609.1894 ns 28,973.116 ns 1.00 0.00 - - - 24 B
MyEnumerator Count 100000 29,561.823 ns 584.5733 ns 488.1452 ns 29,668.355 ns 1.01 0.02 - - - 24 B
BenValueEnumerator Count 100000 152,615.965 ns 2,135.4895 ns 1,997.5382 ns 152,774.774 ns 5.25 0.12 - - - -
MyValueEnumerator Count 100000 152,443.965 ns 2,773.3822 ns 2,594.2234 ns 151,253.140 ns 5.24 0.15 - - - -
Enumerator_Predicate Count_Predicate 100000 200,186.082 ns 2,445.5613 ns 2,167.9264 ns 200,026.952 ns 1.00 0.00 - - - 24 B
MyEnumerator_Predicate Count_Predicate 100000 200,197.706 ns 2,178.2358 ns 1,700.6233 ns 200,308.191 ns 1.00 0.01 - - - 24 B
BenValueEnumerator_Predicate Count_Predicate 100000 266,237.573 ns 5,147.1311 ns 4,298.0876 ns 266,875.275 ns 1.33 0.03 - - - -
MyValueEnumerator_Predicate Count_Predicate 100000 259,023.759 ns 4,147.3925 ns 3,879.4735 ns 257,423.849 ns 1.29 0.02 - - - -
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Configs;
using System;
using System.Collections;
using System.Collections.Generic;
namespace Benchmarks
{
[GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)]
[CategoriesColumn]
[MemoryDiagnoser]
[MarkdownExporterAttribute.GitHub]
public class ValueEnumerableBenchmarks
{
RangeEnumerable source;
[Params(0, 1_000, 100_000)]
public int Count { get; set; }
[GlobalSetup]
public void GlobalSetup()
{
source = new RangeEnumerable(Count);
}
[BenchmarkCategory("Count")]
[Benchmark(Baseline = true)]
public int Enumerator() =>
CountEnumerable<RangeEnumerable, RangeEnumerable.Enumerator, int>(source);
[BenchmarkCategory("Count_Predicate")]
[Benchmark(Baseline = true)]
public int Enumerator_Predicate() =>
CountEnumerable<RangeEnumerable, RangeEnumerable.Enumerator, int>(source, _ => true);
[BenchmarkCategory("Count")]
[Benchmark]
public int MyEnumerator() =>
CountMyEnumerable<RangeEnumerable, RangeEnumerable.MyEnumerator, int>(source);
[BenchmarkCategory("Count_Predicate")]
[Benchmark]
public int MyEnumerator_Predicate() =>
CountMyEnumerable<RangeEnumerable, RangeEnumerable.MyEnumerator, int>(source, _ => true);
[BenchmarkCategory("Count")]
[Benchmark]
public int BenValueEnumerator() =>
CountBenValueEnumerable<RangeEnumerable, RangeEnumerable.BenValueEnumerator, int>(source);
[BenchmarkCategory("Count_Predicate")]
[Benchmark]
public int BenValueEnumerator_Predicate() =>
CountBenValueEnumerable<RangeEnumerable, RangeEnumerable.BenValueEnumerator, int>(source, _ => true);
[BenchmarkCategory("Count")]
[Benchmark]
public int MyValueEnumerator() =>
CountMyValueEnumerable<RangeEnumerable, RangeEnumerable.MyValueEnumerator, int>(source);
[BenchmarkCategory("Count_Predicate")]
[Benchmark]
public int MyValueEnumerator_Predicate() =>
CountMyValueEnumerable<RangeEnumerable, RangeEnumerable.MyValueEnumerator, int>(source, _ => true);
static int CountEnumerable<TEnumerable, TEnumerator, TSource>(TEnumerable source)
where TEnumerable : IEnumerable<TSource>
where TEnumerator: IEnumerator<TSource>
{
var count = 0;
using(var enumerator = (TEnumerator)source.GetEnumerator())
{
while (enumerator.MoveNext())
count++;
}
return count;
}
static int CountEnumerable<TEnumerable, TEnumerator, TSource>(TEnumerable source, Func<TSource, bool> predicate)
where TEnumerable : IEnumerable<TSource>
where TEnumerator: IEnumerator<TSource>
{
var count = 0;
using(var enumerator = (TEnumerator)source.GetEnumerator())
{
while (enumerator.MoveNext())
{
if (predicate(enumerator.Current))
count++;
}
}
return count;
}
static int CountMyEnumerable<TEnumerable, TEnumerator, TSource>(TEnumerable source)
where TEnumerable : IMyEnumerable<TSource>
where TEnumerator: IMyEnumerator<TSource>
{
var count = 0;
using(var enumerator = (TEnumerator)source.GetEnumerator())
{
while (enumerator.MoveNext())
count++;
}
return count;
}
static int CountMyEnumerable<TEnumerable, TEnumerator, TSource>(TEnumerable source, Func<TSource, bool> predicate)
where TEnumerable : IMyEnumerable<TSource>
where TEnumerator: IMyEnumerator<TSource>
{
var count = 0;
using(var enumerator = (TEnumerator)source.GetEnumerator())
{
while (enumerator.MoveNext())
{
if (predicate(enumerator.Current))
count++;
}
}
return count;
}
static int CountBenValueEnumerable<TEnumerable, TEnumerator, TSource>(TEnumerable source)
where TEnumerable : IBenValueEnumerable<TSource, TEnumerator>
where TEnumerator : struct, IBenValueEnumerator<TSource>
{
var count = 0;
using (var enumerator = source.GetValueEnumerator())
{
while (enumerator.TryMoveNext())
count++;
}
return count;
}
static int CountBenValueEnumerable<TEnumerable, TEnumerator, TSource>(TEnumerable source, Func<TSource, bool> predicate)
where TEnumerable : IBenValueEnumerable<TSource, TEnumerator>
where TEnumerator : struct, IBenValueEnumerator<TSource>
{
var count = 0;
using (var enumerator = source.GetValueEnumerator())
{
var current = enumerator.TryGetNext(out var success);
while (success)
{
if (predicate(current))
count++;
current = enumerator.TryGetNext(out success);
}
}
return count;
}
static int CountMyValueEnumerable<TEnumerable, TEnumerator, TSource>(TEnumerable source)
where TEnumerable : IMyValueEnumerable<TEnumerator, TSource>
where TEnumerator : struct, IMyValueEnumerator<TSource>
{
var count = 0;
using(var enumerator = source.GetValueEnumerator())
{
while (enumerator.TryMoveNext())
count++;
}
return count;
}
static int CountMyValueEnumerable<TEnumerable, TEnumerator, TSource>(TEnumerable source, Func<TSource, bool> predicate)
where TEnumerable : IMyValueEnumerable<TEnumerator, TSource>
where TEnumerator : struct, IMyValueEnumerator<TSource>
{
var count = 0;
using(var enumerator = source.GetValueEnumerator())
{
while (enumerator.TryMoveNext(out var current))
{
if (predicate(current))
count++;
}
}
return count;
}
public interface IMyEnumerator<T> : IDisposable
{
T Current { get; }
bool MoveNext();
}
public interface IMyEnumerable<T>
{
IMyEnumerator<T> GetEnumerator();
}
public interface IBenValueEnumerator : IDisposable
{
bool TryMoveNext();
}
public interface IBenValueEnumerator<T> : IBenValueEnumerator
{
T TryGetNext(out bool success);
}
public interface IBenValueEnumerable<TEnumerator>
where TEnumerator : struct, IBenValueEnumerator
{
TEnumerator GetValueEnumerator();
}
public interface IBenValueEnumerable<T, TEnumerator>
where TEnumerator : struct, IBenValueEnumerator<T>
{
TEnumerator GetValueEnumerator();
}
public interface IMyValueEnumerator<T> : IDisposable
{
bool TryMoveNext();
bool TryMoveNext(out T current);
}
public interface IMyValueEnumerable<TEnumerator, T>
where TEnumerator : struct, IMyValueEnumerator<T>
{
TEnumerator GetValueEnumerator();
}
public readonly struct RangeEnumerable
: IEnumerable<int>
, IMyEnumerable<int>
, IBenValueEnumerable<int, RangeEnumerable.BenValueEnumerator>
, IMyValueEnumerable<RangeEnumerable.MyValueEnumerator, int>
{
readonly int count;
internal RangeEnumerable(int count)
{
this.count = count;
}
public Enumerator GetEnumerator() => new Enumerator(count);
IEnumerator<int> IEnumerable<int>.GetEnumerator() => new Enumerator(count);
IEnumerator IEnumerable.GetEnumerator() => new Enumerator(count);
public MyEnumerator GetMyEnumerator() => new MyEnumerator(count);
IMyEnumerator<int> IMyEnumerable<int>.GetEnumerator() => new MyEnumerator(count);
public BenValueEnumerator GetBenValueEnumerator() => new BenValueEnumerator(count);
BenValueEnumerator IBenValueEnumerable<int, RangeEnumerable.BenValueEnumerator>.GetValueEnumerator() => new BenValueEnumerator(count);
public MyValueEnumerator GetMyValueEnumerator() => new MyValueEnumerator(count);
MyValueEnumerator IMyValueEnumerable<RangeEnumerable.MyValueEnumerator, int>.GetValueEnumerator() => new MyValueEnumerator(count);
public struct Enumerator : IEnumerator<int>
{
readonly int count;
int current;
internal Enumerator(int count)
{
this.count = count;
current = -1;
}
public int Current => current;
object IEnumerator.Current => current;
public bool MoveNext() => ++current < count;
public void Reset() => throw new NotSupportedException();
public void Dispose() { }
}
public struct MyEnumerator : IMyEnumerator<int>
{
readonly int count;
int current;
internal MyEnumerator(int count)
{
this.count = count;
current = -1;
}
public int Current => current;
public bool MoveNext() => ++current < count;
public void Dispose() { }
}
public struct BenValueEnumerator : IBenValueEnumerator<int>
{
readonly int count;
int current;
internal BenValueEnumerator(int count)
{
this.count = count;
current = -1;
}
public int TryGetNext(out bool success)
{
success = ++current < count;
if (success)
return current;
return default;
}
public bool TryMoveNext() => ++current < count;
public void Dispose() { }
}
public struct MyValueEnumerator : IMyValueEnumerator<int>
{
readonly int count;
int current;
internal MyValueEnumerator(int count)
{
this.count = count;
current = -1;
}
public bool TryMoveNext(out int current)
{
if (++this.current < count)
{
current = this.current;
return true;
}
current = default;
return false;
}
public bool TryMoveNext() => ++current < count;
public void Dispose() { }
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment