Skip to content

Instantly share code, notes, and snippets.

@m039
Last active March 2, 2017 22:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save m039/bdd4f5cf300378e10e01466da43614cb to your computer and use it in GitHub Desktop.
Save m039/bdd4f5cf300378e10e01466da43614cb to your computer and use it in GitHub Desktop.
C# structs and classes as wrappers, performance benchmark
using System;
using System.Diagnostics;
namespace VoidSharedProject
{
// Results:
// 1: 00:00:47.3721840
// 2: 00:01:14.6771620
// 3: 00:00:10.9821360
// 4: 00:00:20.9437850
// 5: 00:00:42.9371950
// 6: 00:00:24.0811930
// Main thoughts are:
// - A wrapper is twice expensive than an extension method and an extension method is twice expensive as a normal one.
// - Obviously structures are better than classes as wrappers.
// - Second use of a wrapper is very cheap, like an extension method.
public class A
{
private int bb = 14;
public int b()
{
return bb;
}
}
public interface IA
{
int BB();
}
public struct RefStruct<T>
{
internal T r;
public RefStruct(T r)
{
this.r = r;
}
}
public struct AWrapper : IA
{
internal A a;
public AWrapper(A a)
{
this.a = a;
}
public int BB()
{
return a.b();
}
public static implicit operator AWrapper(A a)
{
return new AWrapper(a);
}
}
public class RefClass<T>
{
internal T r;
public RefClass(T r)
{
this.r = r;
}
}
public static class Extensions
{
public static RefStruct<T> ToStruct<T>(this T a)
{
return new RefStruct<T>(a);
}
public static RefClass<T> ToClass<T>(this T a)
{
return new RefClass<T>(a);
}
public static int GetB(this RefStruct<A> ia)
{
return ia.r.b();
}
public static int GetB(this RefClass<A> ia)
{
return ia.r.b();
}
public static int GetB(this A a)
{
return a.b();
}
}
public class Test
{
public static int T()
{
const int count = 100000000;
Stopwatch stopWatch;
int sum = 0;
var a = new A();
// 0, warm up
for (var i = 0; i < count / 100; i++) {
sum += 1;
}
// 1
stopWatch = new Stopwatch();
stopWatch.Start();
for (var i = 0; i < count; i++) {
a.ToStruct().GetB();
a.ToStruct().GetB();
a.ToStruct().GetB();
a.ToStruct().GetB();
a.ToStruct().GetB();
a.ToStruct().GetB();
a.ToStruct().GetB();
a.ToStruct().GetB();
a.ToStruct().GetB();
}
stopWatch.Stop();
Console.WriteLine("1: " + stopWatch.Elapsed);
// 2
sum = 0;
stopWatch = new Stopwatch();
stopWatch.Start();
for (var i = 0; i < count; i++) {
a.ToClass().GetB();
a.ToClass().GetB();
a.ToClass().GetB();
a.ToClass().GetB();
a.ToClass().GetB();
a.ToClass().GetB();
a.ToClass().GetB();
a.ToClass().GetB();
a.ToClass().GetB();
}
stopWatch.Stop();
Console.WriteLine("2: " + stopWatch.Elapsed);
// 3
stopWatch = new Stopwatch();
stopWatch.Start();
for (var i = 0; i < count; i++) {
a.b();
a.b();
a.b();
a.b();
a.b();
a.b();
a.b();
a.b();
a.b();
}
stopWatch.Stop();
Console.WriteLine("3: " + stopWatch.Elapsed);
// 4
stopWatch = new Stopwatch();
stopWatch.Start();
for (var i = 0; i < count; i++) {
a.GetB();
a.GetB();
a.GetB();
a.GetB();
a.GetB();
a.GetB();
a.GetB();
a.GetB();
a.GetB();
}
stopWatch.Stop();
Console.WriteLine("4: " + stopWatch.Elapsed);
// 5
stopWatch = new Stopwatch();
stopWatch.Start();
for (var i = 0; i < count; i++) {
((AWrapper)a).BB();
((AWrapper)a).BB();
((AWrapper)a).BB();
((AWrapper)a).BB();
((AWrapper)a).BB();
((AWrapper)a).BB();
((AWrapper)a).BB();
((AWrapper)a).BB();
((AWrapper)a).BB();
}
stopWatch.Stop();
Console.WriteLine("5: " + stopWatch.Elapsed);
// 6
stopWatch = new Stopwatch();
stopWatch.Start();
for (var i = 0; i < count; i++) {
var w = (AWrapper)a;
w.BB();
w.BB();
w.BB();
w.BB();
w.BB();
w.BB();
w.BB();
w.BB();
w.BB();
}
stopWatch.Stop();
Console.WriteLine("6: " + stopWatch.Elapsed);
return 1;
}
}
}
#define JUNK
using System;
using System.Diagnostics;
namespace SharedProject
{
#if JUNK
// With a lot of junk, results:
// 1: 00:01:18.2174800
// 2: 00:01:25.3262710
// 3: 00:01:07.2275850 (100%)
// 4: 00:01:06.4023880
// 5: 00:01:12.6649500
public class A
{
private int bb = 14;
public int b1 = 14;
public int b32 = 14;
public int b4 = 14;
public int b5 = 14;
public int b6 = 14;
public int b7 = 14;
public int[] bs = new int[100];
public int[] b2s = new int[100];
public int b()
{
return bb;
}
}
#else
// Without junk, results:
// 1: 00:00:29.5859890
// 2: 00:00:40.9515950
// 3: 00:00:16.3016150 (100%)
// 4: 00:00:18.7555140
// 5: 00:00:28.0705080
public class A
{
private int bb = 14;
public int b()
{
return bb;
}
}
#endif
public interface IA
{
int BB();
}
public struct RefStruct<T>
{
internal T r;
public RefStruct(T r)
{
this.r = r;
}
}
public struct AWrapper : IA
{
internal A a;
public AWrapper(A a)
{
this.a = a;
}
public int BB()
{
return a.b();
}
public static implicit operator AWrapper(A a)
{
return new AWrapper(a);
}
}
public class RefClass<T>
{
internal T r;
public RefClass(T r)
{
this.r = r;
}
}
public static class Extensions
{
public static RefStruct<T> ToStruct<T>(this T a)
{
return new RefStruct<T>(a);
}
public static RefClass<T> ToClass<T>(this T a)
{
return new RefClass<T>(a);
}
public static int GetB(this RefStruct<A> ia)
{
return ia.r.b();
}
public static int GetB(this RefClass<A> ia)
{
return ia.r.b();
}
public static int GetB(this A a)
{
return a.b();
}
}
public class Test
{
public static int T()
{
const int count = 100000000;
Stopwatch stopWatch;
int sum = 0;
// 0, warm up
for (var i = 0; i < count / 100; i++) {
sum += 1;
}
// 1
stopWatch = new Stopwatch();
stopWatch.Start();
for (var i = 0; i < count; i++) {
new A().ToStruct().GetB();
new A().ToStruct().GetB();
new A().ToStruct().GetB();
}
stopWatch.Stop();
Console.WriteLine("1: " + stopWatch.Elapsed);
// 2
sum = 0;
stopWatch = new Stopwatch();
stopWatch.Start();
for (var i = 0; i < count; i++) {
new A().ToClass().GetB();
new A().ToClass().GetB();
new A().ToClass().GetB();
}
stopWatch.Stop();
Console.WriteLine("2: " + stopWatch.Elapsed);
// 3
stopWatch = new Stopwatch();
stopWatch.Start();
for (var i = 0; i < count; i++) {
new A().b();
new A().b();
new A().b();
}
stopWatch.Stop();
Console.WriteLine("3: " + stopWatch.Elapsed);
// 4
stopWatch = new Stopwatch();
stopWatch.Start();
for (var i = 0; i < count; i++) {
new A().GetB();
new A().GetB();
new A().GetB();
}
stopWatch.Stop();
Console.WriteLine("4: " + stopWatch.Elapsed);
// 5
stopWatch = new Stopwatch();
stopWatch.Start();
for (var i = 0; i < count; i++) {
((AWrapper)new A()).BB();
((AWrapper)new A()).BB();
((AWrapper)new A()).BB();
}
stopWatch.Stop();
Console.WriteLine("5: " + stopWatch.Elapsed);
return 1;
}
}
}
using System;
using System.Diagnostics;
namespace VoidSharedProject
{
// 1: 00:00:15.7232990
// 2: 00:00:27.3071830
// 3: 00:00:04.3568800
// 4: 00:00:07.7676690
// 5: 00:00:16.3462180
public class A
{
private int bb = 14;
public int b()
{
return bb;
}
}
public interface IA
{
int BB();
}
public struct RefStruct<T>
{
internal T r;
public RefStruct(T r)
{
this.r = r;
}
}
public struct AWrapper : IA
{
internal A a;
public AWrapper(A a)
{
this.a = a;
}
public int BB()
{
return a.b();
}
public static implicit operator AWrapper(A a)
{
return new AWrapper(a);
}
}
public class RefClass<T>
{
internal T r;
public RefClass(T r)
{
this.r = r;
}
}
public static class Extensions
{
public static RefStruct<T> ToStruct<T>(this T a)
{
return new RefStruct<T>(a);
}
public static RefClass<T> ToClass<T>(this T a)
{
return new RefClass<T>(a);
}
public static int GetB(this RefStruct<A> ia)
{
return ia.r.b();
}
public static int GetB(this RefClass<A> ia)
{
return ia.r.b();
}
public static int GetB(this A a)
{
return a.b();
}
}
public class Test
{
public static int T()
{
const int count = 100000000;
Stopwatch stopWatch;
int sum = 0;
var a = new A();
// 0, warm up
for (var i = 0; i < count / 100; i++) {
sum += 1;
}
// 1
stopWatch = new Stopwatch();
stopWatch.Start();
for (var i = 0; i < count; i++) {
a.ToStruct().GetB();
a.ToStruct().GetB();
a.ToStruct().GetB();
}
stopWatch.Stop();
Console.WriteLine("1: " + stopWatch.Elapsed);
// 2
sum = 0;
stopWatch = new Stopwatch();
stopWatch.Start();
for (var i = 0; i < count; i++) {
a.ToClass().GetB();
a.ToClass().GetB();
a.ToClass().GetB();
}
stopWatch.Stop();
Console.WriteLine("2: " + stopWatch.Elapsed);
// 3
stopWatch = new Stopwatch();
stopWatch.Start();
for (var i = 0; i < count; i++) {
a.b();
a.b();
a.b();
}
stopWatch.Stop();
Console.WriteLine("3: " + stopWatch.Elapsed);
// 4
stopWatch = new Stopwatch();
stopWatch.Start();
for (var i = 0; i < count; i++) {
a.GetB();
a.GetB();
a.GetB();
}
stopWatch.Stop();
Console.WriteLine("4: " + stopWatch.Elapsed);
// 5
stopWatch = new Stopwatch();
stopWatch.Start();
for (var i = 0; i < count; i++) {
((AWrapper)a).BB();
((AWrapper)a).BB();
((AWrapper)a).BB();
}
stopWatch.Stop();
Console.WriteLine("5: " + stopWatch.Elapsed);
return 1;
}
}
}
using System;
using System.Diagnostics;
namespace VoidSharedProject
{
// Results:
// 1: 00:00:47.3503060
// 2: 00:01:33.3255210
// 3: 00:00:11.7213860
// 4: 00:00:22.9640250
// 5: 00:00:46.8433780
public class A
{
private int bb = 14;
public int b()
{
return bb;
}
}
public interface IA
{
int BB();
}
public struct RefStruct<T>
{
internal T r;
public RefStruct(T r)
{
this.r = r;
}
}
public struct AWrapper : IA
{
internal A a;
public AWrapper(A a)
{
this.a = a;
}
public int BB()
{
return a.b();
}
public static implicit operator AWrapper(A a)
{
return new AWrapper(a);
}
}
public class RefClass<T>
{
internal T r;
public RefClass(T r)
{
this.r = r;
}
}
public static class Extensions
{
public static RefStruct<T> ToStruct<T>(this T a)
{
return new RefStruct<T>(a);
}
public static RefClass<T> ToClass<T>(this T a)
{
return new RefClass<T>(a);
}
public static int GetB(this RefStruct<A> ia)
{
return ia.r.b();
}
public static int GetB(this RefClass<A> ia)
{
return ia.r.b();
}
public static int GetB(this A a)
{
return a.b();
}
}
public class Test
{
public static int T()
{
const int count = 100000000;
Stopwatch stopWatch;
int sum = 0;
var a = new A();
// 0, warm up
for (var i = 0; i < count / 100; i++) {
sum += 1;
}
// 1
stopWatch = new Stopwatch();
stopWatch.Start();
for (var i = 0; i < count; i++) {
a.ToStruct().GetB();
a.ToStruct().GetB();
a.ToStruct().GetB();
a.ToStruct().GetB();
a.ToStruct().GetB();
a.ToStruct().GetB();
a.ToStruct().GetB();
a.ToStruct().GetB();
a.ToStruct().GetB();
}
stopWatch.Stop();
Console.WriteLine("1: " + stopWatch.Elapsed);
// 2
sum = 0;
stopWatch = new Stopwatch();
stopWatch.Start();
for (var i = 0; i < count; i++) {
a.ToClass().GetB();
a.ToClass().GetB();
a.ToClass().GetB();
a.ToClass().GetB();
a.ToClass().GetB();
a.ToClass().GetB();
a.ToClass().GetB();
a.ToClass().GetB();
a.ToClass().GetB();
}
stopWatch.Stop();
Console.WriteLine("2: " + stopWatch.Elapsed);
// 3
stopWatch = new Stopwatch();
stopWatch.Start();
for (var i = 0; i < count; i++) {
a.b();
a.b();
a.b();
a.b();
a.b();
a.b();
a.b();
a.b();
a.b();
}
stopWatch.Stop();
Console.WriteLine("3: " + stopWatch.Elapsed);
// 4
stopWatch = new Stopwatch();
stopWatch.Start();
for (var i = 0; i < count; i++) {
a.GetB();
a.GetB();
a.GetB();
a.GetB();
a.GetB();
a.GetB();
a.GetB();
a.GetB();
a.GetB();
}
stopWatch.Stop();
Console.WriteLine("4: " + stopWatch.Elapsed);
// 5
stopWatch = new Stopwatch();
stopWatch.Start();
for (var i = 0; i < count; i++) {
((AWrapper)a).BB();
((AWrapper)a).BB();
((AWrapper)a).BB();
((AWrapper)a).BB();
((AWrapper)a).BB();
((AWrapper)a).BB();
((AWrapper)a).BB();
((AWrapper)a).BB();
((AWrapper)a).BB();
}
stopWatch.Stop();
Console.WriteLine("5: " + stopWatch.Elapsed);
return 1;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment