Last active
May 11, 2016 14:41
-
-
Save ig-sinicyn/29a2d814060a58c531039c82bdd3704b to your computer and use it in GitHub Desktop.
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.Diagnostics; | |
namespace CodeDrafts | |
{ | |
static class Program | |
{ | |
struct A | |
{ | |
public uint a1; | |
public uint a2; | |
} | |
struct B | |
{ | |
public ulong b1; | |
} | |
//[MethodImpl(MethodImplOptions.NoInlining)] | |
unsafe static B FromAUnsafe(A a) | |
{ | |
return *(B*)&a; | |
} | |
//[MethodImpl(MethodImplOptions.NoInlining)] | |
static B FromA(A a) | |
{ | |
return new B { b1 = (ulong)a.a2 << 32 | a.a1 }; | |
} | |
static void Main(string[] args) | |
{ | |
Console.WriteLine(IntPtr.Size == 4? "x86" : "x64"); | |
Console.WriteLine(typeof(string).Assembly.FullName); | |
Console.WindowWidth = 120; | |
const int Count = 100 * 1000 * 1000; | |
Measure("Original", () => | |
{ | |
var a = new A() { a1 = 1, a2 = 2 }; | |
var b = new B(); | |
for (int i = 0; i < Count; i++) | |
{ | |
b = FromA(a); | |
} | |
return Count; | |
}); | |
Measure("OptimisedNoCall", () => | |
{ | |
var a = new A() { a1 = 1, a2 = 2 }; | |
var b = new B(); | |
for (int i = 0; i < Count; i++) | |
{ | |
b = FromAUnsafe(a); | |
} | |
return Count; | |
}); | |
Measure("OptimisedWithCall", () => | |
{ | |
var a = new A() { a1 = 1, a2 = 2 }; | |
var b = new B(); | |
for (int i = 0; i < Count; i++) | |
{ | |
b = FromAUnsafe(a); | |
} | |
SimpleCall(b); | |
return Count; | |
}); | |
Measure("OptimisedCallBox", () => | |
{ | |
var a = new A() { a1 = 1, a2 = 2 }; | |
var b = new B(); | |
for (int i = 0; i < Count; i++) | |
{ | |
b = FromAUnsafe(a); | |
} | |
CallBoxed(b); | |
return Count; | |
}); | |
Measure("OptimisedCallBoxStore", () => | |
{ | |
var a = new A() { a1 = 1, a2 = 2 }; | |
var b = new B(); | |
for (int i = 0; i < Count; i++) | |
{ | |
b = FromAUnsafe(a); | |
} | |
CallStoreBoxed(b); | |
return Count; | |
}); | |
Measure("OptimisedCallStore", () => | |
{ | |
var a = new A() { a1 = 1, a2 = 2 }; | |
var b = new B(); | |
for (int i = 0; i < Count; i++) | |
{ | |
b = FromAUnsafe(a); | |
} | |
CallStore(b); | |
return Count; | |
}); | |
Console.Write("Done..."); | |
Console.ReadKey(); | |
} | |
private static void SimpleCall(B b) | |
{ | |
} | |
private static void CallBoxed(object b) | |
{ | |
} | |
private static object _b1; | |
private static void CallStoreBoxed(object b) | |
{ | |
_b1 = b; | |
} | |
private static B _b2; | |
private static void CallStore(B b) | |
{ | |
_b2 = b; | |
} | |
private static void Measure(string name, Func<long> callback) | |
{ | |
GC.Collect(); | |
GC.WaitForPendingFinalizers(); | |
GC.Collect(); | |
var mem = GC.GetTotalMemory(true); | |
var gc00 = GC.CollectionCount(0); | |
var gc01 = GC.CollectionCount(1); | |
var gc02 = GC.CollectionCount(2); | |
var sw = Stopwatch.StartNew(); | |
var result = callback(); | |
sw.Stop(); | |
var mem2 = GC.GetTotalMemory(false); | |
var gc10 = GC.CollectionCount(0); | |
var gc11 = GC.CollectionCount(1); | |
var gc12 = GC.CollectionCount(2); | |
var memDelta = (mem2 - mem) / 1024.0; | |
var gcDelta0 = gc10 - gc00; | |
var gcDelta1 = gc11 - gc01; | |
var gcDelta2 = gc12 - gc02; | |
Console.WriteLine( | |
"{0,22}: {1,5}ms, ips: {2,22:N} | Mem: {3,9:N2} kb, GC 0/1/2: {4}/{5}/{6} => {7,6}", | |
name, sw.ElapsedMilliseconds, result / sw.Elapsed.TotalSeconds, memDelta, gcDelta0, gcDelta1, gcDelta2, result); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment