Re: Reflection in 1.1 and 2.0
- From: Stuart Carnie <stuart.carnie@xxxxxxxxxxxxx>
- Date: Mon, 18 Sep 2006 15:47:11 -0700
I'd suggest you take advantage of Lightweight Code Generation (LCG).
I knocked a v2.0 sample together using your example.
NO LCG:
Runtime version = 2.0.50727.42
Iterations = 1,000,000
00:00:04.8898738
USING LCG:
Runtime version = 2.0.50727.42
Iterations = 1,000,000
00:00:00.0937632
- - - - - COPY BELOW - - - - - -
#define LCG
// remove this define to use the old PropertyInfo way.
using System;
using System.Reflection;
using System.Reflection.Emit;
public class Person
{
private string _firstName;
private string _lastName;
private int _age;
public string FirstName
{
get { return _firstName; }
set { _firstName = value; }
}
public string LastName
{
get { return _lastName; }
set { _lastName = value; }
}
public int Age
{
get { return _age; }
set { _age = value; }
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Runtime version = {0}", Environment.Version);
int iterations = args.Length > 0 ? int.Parse(args[0]) : 1000000;
Console.WriteLine("Iterations = {0}", iterations.ToString("N0"));
Person person = new Person();
person.FirstName = "Hello";
PropertyInfo fn = typeof(Person).GetProperty("FirstName");
PropertyInfo ln = typeof(Person).GetProperty("LastName");
PropertyInfo age = typeof(Person).GetProperty("Age");
DateTime start = DateTime.Now;
#if LCG
FastSetterDelegate<string> fns = GenerateFastSetter<string>(fn);
FastSetterDelegate<string> lns = GenerateFastSetter<string>(ln);
FastSetterDelegate<int> ages = GenerateFastSetter<int>(age);
for (int i = 0; i < iterations; i++)
{
fns(person, "John");
lns(person, "Doe");
ages(person, 42);
}
#else
for (int i = 0; i < iterations; i++)
{
fn.SetValue(person, "John", null);
ln.SetValue(person, "Doe", null);
age.SetValue(person, 42, null);
}
#endif
Console.WriteLine(DateTime.Now - start);
}
static FastSetterDelegate<T> GenerateFastSetter<T>(PropertyInfo pi)
{
DynamicMethod dm = new DynamicMethod(pi.Name, null, new Type[] { typeof(object), typeof(T) }, typeof(Program).Module);
ILGenerator il = dm.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldarg_1);
il.EmitCall(OpCodes.Callvirt, pi.GetSetMethod(), null);
il.Emit(OpCodes.Ret);
return (FastSetterDelegate<T>)dm.CreateDelegate(typeof(FastSetterDelegate<T>));
}
delegate void FastSetterDelegate<T>(object obj, T value);
}
Eric wrote:
I have here a little sample which does reflection on a class..
I striked me that 1.1 is nearly two times faster.
Could me somebody give a hint why?
For the sample: Compile it via "csc.exe /optimize+ Program.cs" with the two compiler for 1.1 and 2.0.
Thanks
Eric
namespace ComponentProfiling
{
using System;
using System.ComponentModel;
using System.Reflection;
public sealed class Person
{
private string _firstName;
private string _lastName;
private int _age;
public string FirstName
{
get { return _firstName; }
set { _firstName = value; }
}
public string LastName
{
get { return _lastName; }
set { _lastName = value; }
}
public int Age
{
get { return _age; }
set { _age = value; }
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Runtime version = {0}", Environment.Version);
int iterations = args.Length > 0 ? int.Parse(args[0]) : 1000000;
Console.WriteLine("Iterations = {0}", iterations.ToString("N0"));
Person person = new Person();
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(Person));
string test1 = typeof(TypeDescriptor).Name;
TimeSpan span1 = Measure(iterations, person,
properties["FirstName"],
properties["LastName"],
properties["Age"]);
Console.WriteLine("{0} = {1}", test1, span1);
string test2 = typeof(MyPropertyDescriptor).Name;
TimeSpan span2 = Measure(iterations, person,
new MyPropertyDescriptor(typeof(Person).GetProperty("FirstName")),
new MyPropertyDescriptor(typeof(Person).GetProperty("LastName")),
new MyPropertyDescriptor(typeof(Person).GetProperty("Age")));
Console.WriteLine("{0} = {1}", test2, span2);
Console.WriteLine("{0}/{1} = {2:P}", test1, test2, span1.TotalMilliseconds / span2.TotalMilliseconds);
Console.WriteLine("Press ENTER to end.");
Console.ReadLine();
}
static TimeSpan Measure(int iterations, Person person, params PropertyDescriptor[] properties)
{
DateTime start;
start = DateTime.Now;
for (int i = 0; i < iterations; i++)
{
properties[0].SetValue(person, "John");
properties[1].SetValue(person, "Doe");
properties[2].SetValue(person, 22); }
return DateTime.Now - start;
}
public sealed class MyPropertyDescriptor : PropertyDescriptor
{
private readonly PropertyInfo _property;
public MyPropertyDescriptor(PropertyInfo property)
:
base(property.Name, null)
{
_property = property;
}
public override bool CanResetValue(object component)
{
return false;
}
public override object GetValue(object component)
{
return _property.GetValue(component, null);
}
public override void ResetValue(object component)
{
throw new NotSupportedException();
}
public override void SetValue(object component, object value)
{
_property.SetValue(component, value, null);
}
public override bool ShouldSerializeValue(object component)
{
return false;
}
public override Type ComponentType
{
get { return _property.ReflectedType; }
}
public override bool IsReadOnly
{
get { return !_property.CanWrite; }
}
public override Type PropertyType
{
get { return _property.PropertyType; }
}
}
}
}
- Follow-Ups:
- Re: Reflection in 1.1 and 2.0
- From: Atif Aziz
- Re: Reflection in 1.1 and 2.0
- References:
- Reflection in 1.1 and 2.0
- From: Eric
- Reflection in 1.1 and 2.0
- Prev by Date: Re: Type.GetType
- Next by Date: Re: Reflection in 1.1 and 2.0
- Previous by thread: RE: Reflection in 2.0 twice as slow? (was Reflection in 1.1 and 2.0)
- Next by thread: Re: Reflection in 1.1 and 2.0
- Index(es):
Relevant Pages
|