Last active
July 10, 2016 11:08
-
-
Save HellBrick/195c3c0f097f16bab6b4b5c6b659b654 to your computer and use it in GitHub Desktop.
Enumerator benchmark
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections; | |
using System.Collections.Generic; | |
using System.Linq; | |
using BenchmarkDotNet.Attributes; | |
using BenchmarkDotNet.Configs; | |
using BenchmarkDotNet.Diagnostics.Windows; | |
using BenchmarkDotNet.Jobs; | |
using BenchmarkDotNet.Running; | |
namespace EnumeratorBoxingTest | |
{ | |
internal class Program | |
{ | |
private static void Main( string[] args ) | |
{ | |
var config | |
= ManualConfig | |
.Create( DefaultConfig.Instance ) | |
.With( Job.RyuJitX64 ) | |
.With( new MemoryDiagnoser() ); | |
BenchmarkRunner.Run<EnumeratorBenchmark>( config ); | |
} | |
} | |
public class EnumeratorBenchmark | |
{ | |
private static readonly int[] _array = Enumerable.Range( 0, 50 ).ToArray(); | |
[Benchmark] | |
public void StructEnumerator() | |
{ | |
var collection = new CollectionWithStructEnumerator<int>( _array ); | |
foreach ( var item in collection ) | |
{ | |
} | |
} | |
[Benchmark] | |
public void BoxedStructEnumerator() | |
{ | |
var collection = new CollectionWithStructEnumerator<int>( _array ) as IEnumerable<int>; | |
foreach ( var item in collection ) | |
{ | |
} | |
} | |
[Benchmark] | |
public void ManuallyBoxedStructEnumerator() | |
{ | |
var collection = new CollectionWithManuallyBoxedEnumerator<int>( _array ); | |
foreach ( var item in collection ) | |
{ | |
} | |
} | |
[Benchmark] | |
public void NaiveClassEnumerator() | |
{ | |
var collection = new CollectionWithNaiveClassEnumerator<int>( _array ); | |
foreach ( var item in collection ) | |
{ | |
} | |
} | |
[Benchmark] | |
public void ManualClassEnumerator() | |
{ | |
var collection = new CollectionWithManualClassEnumerator<int>( _array ); | |
foreach ( var item in collection ) | |
{ | |
} | |
} | |
private class CollectionWithNaiveClassEnumerator<T> : IEnumerable<T> | |
{ | |
private readonly T[] _items; | |
public CollectionWithNaiveClassEnumerator( T[] items ) | |
{ | |
_items = items; | |
} | |
public IEnumerator<T> GetEnumerator() | |
{ | |
for ( int i = 0; i < _items.Length; i++ ) | |
yield return _items[ i ]; | |
} | |
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); | |
} | |
private class CollectionWithManualClassEnumerator<T> : IEnumerable<T> | |
{ | |
private readonly T[] _items; | |
public CollectionWithManualClassEnumerator( T[] items ) | |
{ | |
_items = items; | |
} | |
public IEnumerator<T> GetEnumerator() => new Enumerator( _items ); | |
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); | |
public class Enumerator : IEnumerator<T> | |
{ | |
private int _index; | |
private readonly T[] _items; | |
public Enumerator( T[] items ) | |
{ | |
_items = items; | |
_index = -1; | |
Current = default( T ); | |
} | |
public T Current { get; private set; } | |
object IEnumerator.Current => Current; | |
public bool MoveNext() | |
{ | |
_index++; | |
if ( _index >= _items.Length ) | |
return false; | |
Current = _items[ _index ]; | |
return true; | |
} | |
public void Dispose() { } | |
public void Reset() { } | |
} | |
} | |
private class CollectionWithStructEnumerator<T> : IEnumerable<T> | |
{ | |
private readonly T[] _items; | |
public CollectionWithStructEnumerator( T[] items ) | |
{ | |
_items = items; | |
} | |
public StructEnumeratorImpementation<T> GetEnumerator() => new StructEnumeratorImpementation<T>( _items ); | |
IEnumerator<T> IEnumerable<T>.GetEnumerator() => GetEnumerator(); | |
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); | |
} | |
private class CollectionWithManuallyBoxedEnumerator<T> : IEnumerable<T> | |
{ | |
private readonly T[] _items; | |
public CollectionWithManuallyBoxedEnumerator( T[] items ) | |
{ | |
_items = items; | |
} | |
public IEnumerator<T> GetEnumerator() => new BoxedEnumerator<T, StructEnumeratorImpementation<T>>( new StructEnumeratorImpementation<T>( _items ) ); | |
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); | |
} | |
private class BoxedEnumerator<TItem, TEnumerator> : IEnumerator<TItem> where TEnumerator : struct, IEnumerator<TItem> | |
{ | |
private TEnumerator _structEnumerator; | |
public BoxedEnumerator( TEnumerator structEnumerator ) | |
{ | |
_structEnumerator = structEnumerator; | |
} | |
public TItem Current => _structEnumerator.Current; | |
object IEnumerator.Current => Current; | |
public void Dispose() => _structEnumerator.Dispose(); | |
public bool MoveNext() => _structEnumerator.MoveNext(); | |
public void Reset() => _structEnumerator.Reset(); | |
} | |
private struct StructEnumeratorImpementation<T> : IEnumerator<T> | |
{ | |
private int _index; | |
private readonly T[] _items; | |
public StructEnumeratorImpementation( T[] items ) | |
{ | |
_items = items; | |
_index = -1; | |
Current = default( T ); | |
} | |
public T Current { get; private set; } | |
object IEnumerator.Current => Current; | |
public bool MoveNext() | |
{ | |
_index++; | |
if ( _index >= _items.Length ) | |
return false; | |
Current = _items[ _index ]; | |
return true; | |
} | |
public void Dispose() { } | |
public void Reset() { } | |
} | |
} | |
} |
Author
HellBrick
commented
Jul 10, 2016
•
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment