new的原罪
一直以为在开发阶段能够直接调用的,速度而言一定是最优秀的,因为总比后期通过反射之类来调用来得快吧.
下面请看一个SB的例子,重新编译以后,这个类在创建100,000,000实体时居然耗费了16秒的时间:
internal class CreateWithNew<T> : EntityCreator<T> where T : new() { public override T Create() { return new T(); } }//此SB相当荣幸的以为这个调用速度一定是最快的,怎么的也是编译级别的吧
奶奶的,居然还不如之前的解决方案:(创建100,000,000实体约4秒)
/// <summary> /// 根据参数的类型,创建一个句柄,这个句柄可以根据对应的参数列表创建指定的实例 /// </summary> /// <param name="parameterTypes">参数类型列表</param> /// <returns>用于创建实例的句柄</returns> private static Func<object[], TType> GenerateCreateInstanceHandler(Type[] parameterTypes) { Type type = typeof(TType); if (type.IsSealed && type.IsAbstract) { throw new NotSupportedException(string.Concat("不支持用于创建静态类型的实例:", Reflector.GetTypeName(type))); } if (type.IsArray || type.IsEnum || type.IsGenericTypeDefinition || type.IsGenericParameter) { throw new NotSupportedException(string.Concat("不支持用于创建数组,枚举,泛型定义,泛型参数的实例:", Reflector.GetTypeName(type))); } if (type.IsNotPublic && (type.IsInterface || type.IsAbstract)) { throw new NotSupportedException(string.Concat("不支持用于创建非公开的接口及抽象类型的实例:", Reflector.GetTypeName(type))); } //if (type.IsAbstract || type.IsInterface) //{ // TypeFactory factory = TypeFactory.Create(type); // factory.ImplementBase(); // type = factory.CreateType(); //} ConstructorInfo constructor = Reflector.GetConstructor(type, parameterTypes); DynamicMethodFactory<Func<object[], TType>> method = DynamicMethodFactory<Func<object[], TType>>.Create("CreateInstance"); /* * If found match constructor, then invoke it. * Else if found any constructor, use default parameters. */ MethodInfo convert = new Func<object[], int, object>(GetParameter<object>).Method.GetGenericMethodDefinition(); if (constructor != null) { #region Use a match constructor to create a new instance ParameterInfo[] parameters = constructor.GetParameters(); if (type.IsClass) { int len = parameterTypes.Length; for (int i = 0; i < len; i++) { ParameterInfo p = parameters[i]; method.LoadArg(0).Load(i); method.Call(convert.MakeGenericMethod(p.ParameterType)); } method.New(constructor).Return(); } else { LocalBuilder result = method.Declare(type); method.LoadVarAddr(result); int len = parameterTypes.Length; for (int i = 0; i < len; i++) { ParameterInfo p = parameters[i]; method.LoadArg(0).Load(i); method.Call(convert.MakeGenericMethod(p.ParameterType)); } method.Call(constructor); method.LoadVar(result).Return(); } #endregion } else { method.LoadDefault<TType>().Return(); } return method.Delegation; }
奶奶的 ,抽象类居然被委托打败了,我很想学着穿越小说里面的SB配角大喊一声:怎么可能
于是开始分析,我X他娘的,居然发现NEW()被解释成了这个,他妈的这还不如直接反射算了
System.Activator.CreateInstance()
于是果断修改成这样:
if (con.IsPublic && type.IsPublic) { Type parent = typeof (EntityCreator<T>); TypeFactory factory = TypeFactory.Create(parent); factory.DefineOverride(parent.GetMethod("Create"), m => { m.New(con).Return(); }); Type creator = factory.CreateType(); Createor = Reflector.CreateInstanceAs<EntityCreator<T>>(creator); } else { Createor = new CreateWithPrivateNew<T>(); }
接下来表现如何?
2.6秒!!!
OK,我心里平衡了.