Skip to content

Instantly share code, notes, and snippets.

@mburbea
Created January 22, 2015 16:36
Show Gist options
  • Save mburbea/683f74ff5cc589d512c5 to your computer and use it in GitHub Desktop.
Save mburbea/683f74ff5cc589d512c5 to your computer and use it in GitHub Desktop.
StructEnumerator
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