软件测试中有关Emit与Reflection性能对比测试

发表于:2009-05-21来源:作者:点击数: 标签:软件测试性能ReflectionEmit
使用Emit代替反射性能提升比较多,不过使用Emit需要将DynamicMethod缓存起来,缓存太多也不好,所以可以使用一些折中方法。 例如NHibernate,使用Emit读取/设置实体属性时,生成的DynamicMethod每次读取/设置全部的属性值,读取时返回一个object[],设置时提
使用Emit代替反射性能提升比较多,不过使用Emit需要将DynamicMethod缓存起来,缓存太多也不好,所以可以使用一些折中方法。
例如NHibernate,使用Emit读取/设置实体属性时,生成的DynamicMethod每次读取/设置全部的属性值,读取时返回一个object[],设置时提供一个包含各个属性值的object[]数组。在SELECT时使用这种方式一次设置好所有属性;在INSERT、UPDATE时则一次读出全部属性;在DELETE时则可以直接使用反射从实体上读取identity属性,因为从应用层面总体来看反射的性能还是比较好的。

Emit跟反射的性能测试对比如下:

Emit、Reflection代码:
//A delegate for the dynamic method
public delegate object GetPropertyValueInvoker(object obj);

public class EmitTest
{
    private static GetPropertyValueInvoker GetEmitInvoker(Type type, string propertyName)
    {
        PropertyInfo propInfo = type.GetProperty(propertyName
            , BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

        //Create a DynamicMethod
        Type ownerType = type.IsInterface ? typeof(object) : type;
        bool canSkipChecks = SecurityManager.IsGranted(new ReflectionPermission(ReflectionPermissionFlag.MemberAclearcase/" target="_blank" >ccess));
        DynamicMethod method = new DynamicMethod(string.Empty, typeof(object)
            , new Type[] { typeof(object) }, ownerType, canSkipChecks);

        //Use ILGenerator to build the method body’s IL code
        ILGenerator il = method.GetILGenerator();
        //Load the first argument of the method call onto stack
        il.Emit(OpCodes.Ldarg_0);
        //Necessary type conversion
        if (type.IsValueType)
            il.Emit(OpCodes.Unbox, type);
        else [Page]
            il.Emit(OpCodes.Castclass, type);
        //Call the property’s get method
        il.EmitCall(OpCodes.Callvirt, propInfo.GetGetMethod(true), null);
        //If getter return a value type, box it to object
        if (propInfo.PropertyType.IsValueType)
        {
            il.Emit(OpCodes.Box, propInfo.PropertyType);
        }
        //Return the value of the property
        il.Emit(OpCodes.Ret);

        //Create a delegate for the client to call the dynamic method
        GetPropertyValueInvoker getInvoker = 
            (GetPropertyValueInvoker)method.CreateDelegate(typeof(GetPropertyValueInvoker));

        return getInvoker;
    }
    //simply cache the dynamic method for the type TestEntity
    private static IDictionary<string, GetPropertyValueInvoker> _invokerCache 
        = new Dictionary<string, GetPropertyValueInvoker>(3);

    //Use the dynamic method, which is generated by using Emit every time, to  get the property’s value

原文转自:http://www.ltesting.net