Created
June 22, 2017 16:38
-
-
Save Tornhoof/2bb73db914a13825ec7c0eb89d8d6b6a to your computer and use it in GitHub Desktop.
Nameof vs. Expression Tree Member Names Benchmark
This file contains 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
``` ini | |
BenchmarkDotNet=v0.10.8, OS=Windows 10 Redstone 2 (10.0.15063) | |
Processor=Intel Core i7-4790K CPU 4.00GHz (Haswell), ProcessorCount=8 | |
Frequency=3906243 Hz, Resolution=256.0005 ns, Timer=TSC | |
[Host] : Clr 4.0.30319.42000, 64bit RyuJIT-v4.7.2098.0 | |
DefaultJob : Clr 4.0.30319.42000, 64bit RyuJIT-v4.7.2098.0 | |
``` | |
| Method | Mean | Error | StdDev | Gen 0 | Allocated | | |
|-------------------------- |--------------:|-----------:|----------:|-------:|----------:| | |
| NameOfBenchmark | 0.0002 ns | 0.0010 ns | 0.0009 ns | - | 0 B | | |
| ExpressionBenchmark | 1,394.7139 ns | 10.5833 ns | 9.8996 ns | 0.2117 | 888 B | | |
| ExpressionNameOfBenchmark | 824.3050 ns | 4.2835 ns | 4.0068 ns | 0.1335 | 560 B | | |
using System; | |
using System.Linq.Expressions; | |
using BenchmarkDotNet.Attributes; | |
using BenchmarkDotNet.Diagnostics.Windows.Configs; | |
namespace NameofBench | |
{ | |
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
BenchmarkDotNet.Running.BenchmarkRunner.Run<ClassMemberBench>(); | |
} | |
} | |
[InliningDiagnoser] | |
[MemoryDiagnoser] | |
public class ClassMemberBench | |
{ | |
public void UseNames(string className, string memberName) | |
{ | |
} | |
public void UseNames<T>(Expression<Func<T, object>> expression) | |
{ | |
MemberExpression member = expression.Body as MemberExpression; | |
if (member == null) | |
{ | |
// The property access might be getting converted to object to match the func | |
// If so, get the operand and see if that's a member expression | |
member = (expression.Body as UnaryExpression)?.Operand as MemberExpression; | |
} | |
if (member == null) | |
{ | |
throw new ArgumentException("Action must be a member expression."); | |
} | |
// Pass the names on to the string-based UseNames method | |
UseNames(typeof(T).Name, member.Member.Name); | |
} | |
public void UseNames<T>(Expression<Func<T, string>> expression) | |
{ | |
ConstantExpression constant = expression.Body as ConstantExpression; | |
if (constant == null) | |
{ | |
throw new ArgumentException("Expression must be a constant expression."); | |
} | |
UseNames(typeof(T).Name, constant.Value.ToString()); | |
} | |
[Benchmark] | |
public void NameOfBenchmark() | |
{ | |
UseNames(nameof(Foo), nameof(Foo.Bar)); | |
} | |
[Benchmark] | |
public void ExpressionBenchmark() | |
{ | |
UseNames<Foo>(t => t.Bar); | |
} | |
[Benchmark] | |
public void ExpressionNameOfBenchmark() | |
{ | |
UseNames<Foo>(t => nameof(t.Baz)); | |
} | |
} | |
public class Foo | |
{ | |
public int Bar { get; set; } // integer so it uses Func<T, object> | |
public void Baz() | |
{ | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment