Upload
buu-nguyen
View
3.157
Download
4
Embed Size (px)
DESCRIPTION
Fasterflect (read either "Faster-flect" or "Fast-reflect") provides an alternative to the .NET Reflection API and is optimized for frequently used reflection features. The API addresses two problems of the built-in .NET Reflection API: verbose code and slow performance.
Citation preview
ULTRA FAST DYNAMIC INVOCATION IN .NET
WITH FASTERFLECT
Buu Nguyen
Buu Nguyen
Director of Technology, KMS Technology, www.kms-technology.com
Lecturer, RMIT Vietnam, www.rmit.edu.vn
www.buunguyen.net/blog Twitter: buunguyen
Fasterflect is an open-source .NET library that
makes the task of dynamically constructing objects and invoking methods, properties, fields etc.
much simpler and (up to
400x) faster than the
standard .NET Reflection API
Agenda
Overview of .NET Reflection Capabilities
How Fasterflect Helps with Invocation Using Fasterflect & Benchmark The Design of Fasterflect Future Direction
.NET Reflection
#3 - Produce dynamic assemblies
#2 - Perform dynamic invocation
#1 - Retrieve assemblies’ metadata
#1 & #3 are well addressed, can hardly improve
That leaves
#2…
Complicated & Slow
How complicated? Lookup metadata before invoking Lookup & invoke require many
parametersHard to get right
Poor support for value type How slow?
Up to 400 time slower than FF.
class Person{ private int id; private String name; private int calories; private static int instanceCount;
public int Age { get; set; } public String NickName { get; set; }
public Person(int id, string name) { this.id = id; this.name = name; instanceCount++; } public void Eat(int calories) { this.calories += calories; } public int GetCaloriesEaten() { return calories; } public static int GetInstanceCount() { return instanceCount; }}
Fasterflect Being Simpler .NET Reflection
var obj = type.Construct(10, "John");string name = obj.SetField("name", "Jane“) .GetField<string>("name");
// Invoke constructorConstructorInfo ctor = type.GetConstructor( BindingFlags.Instance | BindingFlags.Public, null, CallingConventions.HasThis, new [] {typeof(int), typeof(string)}, null);object obj = ctor.Invoke(new object[]{10, "John"});
// Update value of 'name' & print out 'name'FieldInfo field = type.GetField("name", BindingFlags.Instance | BindingFlags.NonPublic);field.SetValue(obj, "Jane");string name = (string)field.GetValue(obj);
Fasterflect
…Fasterflect Being Simplervar obj = type.Construct(1, "John");
// Chain property & field settingobj.SetProperty("Age", 20).SetField("id", 20);Console.WriteLine(obj.GetField<int>("id"));
// Set properties & fields via anonymous typeobj.SetProperties(new { Age = 20, NickName = "Jane" }) .SetFields(new { id = 10, name = "Peter" });Console.WriteLine(obj.GetField<string>("name"));
// Chain method callsvar calories = obj.Invoke("Eat", 2000) .Invoke("Eat", 3000) .Invoke<int>("GetCaloriesEaten");Console.WriteLine(calories);
// Invoke static methodvar instanceCount = type.Invoke<int>("GetInstanceCount");Console.WriteLine(instanceCount);
Fasterflect Being Faster
Previous .NET Reflection code executed 2,000,000 iterations 23.2 seconds
vs. same run for Fasterflect 2.7 seconds
x9 gain isn’t impressive? Fasterflect has a weapon for
performance maniacs…
Enter Cached Delegates… Step 1. Generate delegates (once)
Step 2. Invoke
What would the execution time for 2,000,000 iterations be?
var ctor = type.DelegateForConstruct(new[] { typeof(int), typeof(string) });var setter = type.DelegateForSetField("name");var getter = type.DelegateForGetField("name");
var obj = ctor(1, "John");setter(obj, "Jane");string name = (string)getter(obj);
Time of 2,000,000 Calls
144 ms ~160-time increase in performance compared to .NET Reflection
Up to 400-time in some cases (next slide)
Method Invocation Benchmark
Portion of Full Benchmark
Met
hod
Const
ruct
orFiel
d
Prop
erty
0
2000
4000
6000
8000
10000
12000
Direct invokeReflection invokeFasterflect invokeFasterflect cached invoke
Fasterflect Feature Set
Support both reference type & value type Object construction Get/set static/instance fields Get/set static/instance properties Invoke static/instance methods Get/set indexers Get/set array elements Handle ref/out parameters Cache API available for most operations
The Design of Fasterflect
Fluent API is implemented with .NET 3.5 extension methods
The hard part is huge performance gain Invocation info not available at compile
time for early binding Resorting to reflection at runtime is costly
Solution: runtime code generation
Runtime Code Generation
We have enough information at runtime to perform invocation w/o resorting to .NET Reflection, e.g.
We can generate code like this, compile, load into memory, and invoke DirectInvoke() as need
Code Generation Approaches
•Easy to build/debug•Worst performance
Direct C# or CodeDOM
•Much better performance than #1•Require type/module/class definition•Can’t be GC’ed unless unloading app-domain
Dynamic Assembly
•Much better performance than #1•Only focus on method, not module/type/class•Can be GC’ed
Dynamic Method
3000-Feet Workflow
API Delegate Cache
Engine
Client invokes lookups delegate
stores delegate
build
s &
invoke
sEmitter
1Emitter 1Emitter X
generates CIL
TDD is Inevitable
Why? Code complexity (lots of CIL) Goal of being a user-friendly API
Approach Test-first 95%+ test coverage
Future Direction
Add new invocation utilities Integrate with .NET Reflection
metadata Support Silverlight’s CLR and .NET
4.0 CLR Build benchmark against 4.0’s
‘dynamic’ In consideration
Build on .NET 4.0’s DynamicObject Add AOP capability
Download Fasterflect 1.1
http://fasterflect.codeplex.com/ Download include
Binary (.NET 3.5) Source code & CHM doc Sample code Benchmark application Unit test cases
Licensed under Apache 2.0