Skip to content

Commit

Permalink
Convert perf test to use BenchmarkDotNet
Browse files Browse the repository at this point in the history
  • Loading branch information
mattwarren committed Feb 22, 2016
1 parent c16c573 commit 2fdfe29
Show file tree
Hide file tree
Showing 6 changed files with 106 additions and 94 deletions.
187 changes: 95 additions & 92 deletions FastMember.Tests/Program.cs
@@ -1,131 +1,134 @@

using System;
using System.Diagnostics;
using System;
using System.ComponentModel;
using FastMember;
using System.Linq;
using System.Reflection;
using FastMember;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Columns;
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Jobs;
using BenchmarkDotNet.Loggers;
using BenchmarkDotNet.Running;
using BenchmarkDotNet.Exporters;

namespace FastMemberTests
{
public class Program
{
public string Value { get; set; }
static void Main()
public class FastMemberPerformance
{
var obj = new Program();
obj.Value = "abc";
GC.KeepAlive(obj.Value);
const int loop = 5000000;
string last = null;
var watch = Stopwatch.StartNew();
for (int i = 0; i < loop; i++)
public string Value { get; set; }

private FastMemberPerformance obj;
private dynamic dlr;
private PropertyInfo prop;
private PropertyDescriptor descriptor;

private TypeAccessor accessor;
private ObjectAccessor wrapped;

private Type type;

public static void Main(string[] args)
{
var summary = BenchmarkRunner.Run<FastMemberPerformance>(new Config());
Console.WriteLine();
// Display a summary to match the output of the original Performance test
foreach (var report in summary.Reports.OrderBy(r => r.Key.Target.MethodTitle))
{
Console.WriteLine("{0}: {1:N2} ns", report.Key.Target.MethodTitle, report.Value.ResultStatistics.Median);
}
Console.WriteLine();
}

[Setup]
public void Setup()
{
obj = new FastMemberPerformance();
dlr = obj;
prop = typeof(FastMemberPerformance).GetProperty("Value");
descriptor = TypeDescriptor.GetProperties(obj)["Value"];

// FastMember specific code
accessor = FastMember.TypeAccessor.Create(typeof(FastMemberPerformance));
wrapped = FastMember.ObjectAccessor.Create(obj);

type = typeof(FastMemberPerformance);
}

[Benchmark(Description = "1. Static C#", Baseline = true)]
public string StaticCSharp()
{
last = obj.Value;
obj.Value = "abc";
return obj.Value;
}
watch.Stop();
Console.WriteLine("Static C#: {0}ms", watch.ElapsedMilliseconds);
#if !NO_DYNAMIC
dynamic dlr = obj;
watch = Stopwatch.StartNew();
for (int i = 0; i < loop; i++)

[Benchmark(Description = "2. Dynamic C#")]
public string DynamicCSharp()
{
last = dlr.Value;
dlr.Value = "abc";
return dlr.Value;
}
watch.Stop();
Console.WriteLine("Dynamic C#: {0}ms", watch.ElapsedMilliseconds);
#endif
var prop = typeof (Program).GetProperty("Value");
watch = Stopwatch.StartNew();
for (int i = 0; i < loop; i++)

[Benchmark(Description = "3. PropertyInfo")]
public string PropertyInfo()
{
last = (string)prop.GetValue(obj, null);
prop.SetValue(obj, "abc", null);
return (string)prop.GetValue(obj, null);
}
watch.Stop();
Console.WriteLine("PropertyInfo: {0}ms", watch.ElapsedMilliseconds);

#if !COREFX
var descriptor = TypeDescriptor.GetProperties(obj)["Value"];
watch = Stopwatch.StartNew();
for (int i = 0; i < loop; i++)
[Benchmark(Description = "4. PropertyDescriptor")]
public string PropertyDescriptor()
{
last = (string)descriptor.GetValue(obj);
descriptor.SetValue(obj, "abc");
return (string)descriptor.GetValue(obj);
}
watch.Stop();
Console.WriteLine("PropertyDescriptor: {0}ms", watch.ElapsedMilliseconds);

Hyper.ComponentModel.HyperTypeDescriptionProvider.Add(typeof(Program));
#endif
//descriptor = TypeDescriptor.GetProperties(obj)["Value"];
//watch = Stopwatch.StartNew();
//for (int i = 0; i < loop; i++)
//{
// last = (string)descriptor.GetValue(obj);
// descriptor.SetValue(obj, "abc");
//}
//watch.Stop();
//Console.WriteLine("HyperPropertyDescriptor: {0}ms", watch.ElapsedMilliseconds);

var accessor = TypeAccessor.Create(typeof (Program));
watch = Stopwatch.StartNew();
for (int i = 0; i < loop; i++)

[Benchmark(Description = "5. TypeAccessor.Create")]
public string TypeAccessor()
{
last = (string)accessor[obj, "Value"];
accessor[obj, "Value"] = "abc";
return (string)accessor[obj, "Value"];
}
watch.Stop();
Console.WriteLine("TypeAccessor.Create: {0}ms", watch.ElapsedMilliseconds);

var wrapped = ObjectAccessor.Create(obj);
watch = Stopwatch.StartNew();
for (int i = 0; i < loop; i++)
[Benchmark(Description = "6. ObjectAccessor.Create")]
public string ObjectAccessor()
{
last = (string)wrapped["Value"];
wrapped["Value"] = "abc";
return (string)wrapped["Value"];
}
watch.Stop();
Console.WriteLine("ObjectAccessor.Create: {0}ms", watch.ElapsedMilliseconds);


object lastObj = null;
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
GC.WaitForPendingFinalizers();
watch = Stopwatch.StartNew();
for (int i = 0; i < loop; i++)
[Benchmark(Description = "7. c# new()")]
public FastMemberPerformance CSharpNew()
{
lastObj = new Program();
return new FastMemberPerformance();
}
watch.Stop();
Console.WriteLine("c# new(): {0}ms", watch.ElapsedMilliseconds);

Type type = typeof (Program);
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
GC.WaitForPendingFinalizers();
watch = Stopwatch.StartNew();
for (int i = 0; i < loop; i++)

[Benchmark(Description = "8. Activator.CreateInstance")]
public object ActivatorCreateInstance()
{
lastObj = Activator.CreateInstance(type);
return Activator.CreateInstance(type);
}
watch.Stop();
Console.WriteLine("Activator.CreateInstance: {0}ms", watch.ElapsedMilliseconds);

GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
GC.WaitForPendingFinalizers();
watch = Stopwatch.StartNew();
for (int i = 0; i < loop; i++)
[Benchmark(Description = "9. TypeAccessor.CreateNew")]
public object TypeAccessorCreateNew()
{
lastObj = accessor.CreateNew();
return accessor.CreateNew();
}
watch.Stop();
Console.WriteLine("TypeAccessor.CreateNew: {0}ms", watch.ElapsedMilliseconds);

GC.KeepAlive(last);
GC.KeepAlive(lastObj);


}

// BenchmarkDotNet settings (you can use the defaults, but these are tailored for this benchmark)
private class Config : ManualConfig
{
public Config()
{
Add(Job.Default.WithLaunchCount(1));
Add(PropertyColumn.Method);
Add(StatisticColumn.Median, StatisticColumn.StdDev);
Add(BaselineDiffColumn.Scaled);
Add(CsvExporter.Default, MarkdownExporter.Default, MarkdownExporter.GitHub);
Add(new ConsoleLogger());
}
}
}
}
Expand Up @@ -38,6 +38,10 @@
<AssemblyOriginatorKeyFile>../FastMember.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
<ItemGroup>
<Reference Include="BenchmarkDotNet, Version=0.9.1.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\BenchmarkDotNet.0.9.1\lib\net40\BenchmarkDotNet.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="nunit.framework, Version=3.0.5797.27534, Culture=neutral, PublicKeyToken=2638cd05610744eb, processorArchitecture=MSIL">
<HintPath>..\packages\NUnit.3.0.0\lib\net45\nunit.framework.dll</HintPath>
<Private>True</Private>
Expand Down
1 change: 1 addition & 0 deletions FastMember_Net40.Signed.Tests/packages.config
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="BenchmarkDotNet" version="0.9.1" targetFramework="net45" />
<package id="NUnit" version="3.0.0" targetFramework="net45" />
</packages>
4 changes: 4 additions & 0 deletions FastMember_Net40.Tests/FastMember_Net40.Tests.csproj
Expand Up @@ -34,6 +34,10 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="BenchmarkDotNet, Version=0.9.1.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\BenchmarkDotNet.0.9.1\lib\net40\BenchmarkDotNet.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.CSharp" />
<Reference Include="nunit.framework, Version=3.0.5797.27539, Culture=neutral, PublicKeyToken=2638cd05610744eb, processorArchitecture=MSIL">
<HintPath>..\packages\NUnit.3.0.0\lib\net40\nunit.framework.dll</HintPath>
Expand Down
3 changes: 2 additions & 1 deletion FastMember_Net40.Tests/packages.config
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="NUnit" version="3.0.0" targetFramework="net40" />
<package id="BenchmarkDotNet" version="0.9.1" targetFramework="net4" />
<package id="NUnit" version="3.0.0" targetFramework="net4" />
</packages>
1 change: 0 additions & 1 deletion Nuget.config
@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<clear />
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
</packageSources>
</configuration>

0 comments on commit 2fdfe29

Please sign in to comment.