Created
January 22, 2015 16:36
-
-
Save mburbea/683f74ff5cc589d512c5 to your computer and use it in GitHub Desktop.
StructEnumerator
This file contains hidden or 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.Generic; | |
using System.Diagnostics; | |
using System.Globalization; | |
using System.Linq; | |
using System.Reflection; | |
using System.Runtime.CompilerServices; | |
namespace ConsoleApplication1 | |
{ | |
internal unsafe class Program | |
{ | |
public struct Argument2Unsafe : IEnumerable<byte> | |
{ | |
public fixed byte _bytes [2]; | |
public IEnumerator<byte> GetEnumerator() | |
{ | |
var e = default(Argument2UnsafeEnumerator); | |
e._f = this; | |
return e; | |
} | |
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() | |
{ | |
return GetEnumerator(); | |
} | |
private struct Argument2UnsafeEnumerator : IEnumerator<byte> | |
{ | |
public Argument2Unsafe _f; | |
private int _i; | |
public byte Current | |
{ | |
get { fixed(byte * bytes = _f._bytes){return bytes[_i-1];} } | |
} | |
public void Dispose() | |
{ | |
} | |
object System.Collections.IEnumerator.Current | |
{ | |
get { return Current; } | |
} | |
public bool MoveNext() | |
{ | |
return _i++ < 2; | |
} | |
public void Reset() | |
{ | |
throw new NotImplementedException(); | |
} | |
} | |
} | |
public struct Arguments2 : IEnumerable<byte> | |
{ | |
public byte _a; | |
public byte _b; | |
byte this[int index] | |
{ | |
get{ | |
switch(index){ | |
case 0: return _a; | |
case 1: return _b; | |
default: throw new ArgumentOutOfRangeException("index"); | |
} | |
} | |
} | |
struct Arguments2Enumerator : IEnumerator<byte> | |
{ | |
public Arguments2 _f; | |
private int _i; | |
public byte Current | |
{ | |
get { return _f[_i - 1]; } | |
} | |
public void Dispose() | |
{ | |
} | |
object System.Collections.IEnumerator.Current | |
{ | |
get { return Current; } | |
} | |
public bool MoveNext() | |
{ | |
return _i++ < 2; | |
} | |
public void Reset() | |
{ | |
throw new NotImplementedException(); | |
} | |
} | |
public IEnumerator<byte> GetEnumerator() | |
{ | |
return new Arguments2Enumerator{_f = this}; | |
} | |
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() | |
{ | |
return GetEnumerator(); | |
} | |
} | |
[MethodImpl(MethodImplOptions.NoInlining)] | |
public static int Sum(IEnumerable<byte> numbers) | |
{ | |
int s = 0; | |
foreach (var num in numbers){ | |
s+=num; | |
} | |
return s; | |
} | |
[MethodImpl(MethodImplOptions.NoInlining)] | |
public static int CallWithArray(byte a, byte b) | |
{ | |
return Sum(new[] {a, b}); | |
} | |
[MethodImpl(MethodImplOptions.NoInlining)] | |
public static int CallWithList(byte a, byte b) | |
{ | |
return Sum(new List<byte> { a, b}); | |
} | |
[MethodImpl(MethodImplOptions.NoInlining)] | |
public static int CallWithArg2(byte a, byte b) | |
{ | |
return Sum(new Arguments2{ _a= a, _b=b}); | |
} | |
[MethodImpl(MethodImplOptions.NoInlining)] | |
public static int CallWithArg2Unsafe(byte a, byte b) | |
{ | |
var u = default(Argument2Unsafe); | |
u._bytes[0] = a; | |
u._bytes[1] = b; | |
//fixed(byte* bytes = u._bytes){ | |
// bytes[0] = a; | |
// bytes[1] = b; | |
//} | |
return Sum(u); | |
} | |
private static void Main(string[] args) | |
{ | |
foreach (var test in Tests) | |
{ | |
Console.WriteLine(test.Invoke(1, 2)); | |
} | |
int maxMethodLength = Tests.Select(x => GetMethodName(x.Method).Length).Max(); | |
RunTests(1, false, maxMethodLength); | |
RunTests(1 << 24, true, maxMethodLength); | |
} | |
private static Func<byte, byte, int>[] Tests = | |
{ | |
CallWithArray, CallWithList, CallWithArg2,CallWithArg2Unsafe | |
}; | |
private static string GetMethodName(MethodInfo method) | |
{ | |
return method.IsGenericMethod | |
? string.Format(@"{0}<{1}>", method.Name, string.Join<Type>(",", method.GetGenericArguments())) | |
: method.Name; | |
} | |
private static void RunTests(int count, bool displayResults, int maxLength) | |
{ | |
foreach (var action in Tests) | |
{ | |
Stopwatch sw = Stopwatch.StartNew(); | |
for (int i = 0; i < count; i++) | |
{ | |
action(1, 2); | |
} | |
sw.Stop(); | |
if (displayResults) | |
{ | |
Console.WriteLine("{0}: {1}ms", GetMethodName(action.Method).PadRight(maxLength), | |
((int) sw.ElapsedMilliseconds).ToString(CultureInfo.InvariantCulture).PadLeft(6)); | |
} | |
GC.Collect(); | |
GC.WaitForPendingFinalizers(); | |
GC.Collect(); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment