C# Activator.CreateInstance<;T>;vs编译表达式。两台不同机器上的反向性能
我和一位朋友在使用编译表达式而不是C# Activator.CreateInstance<;T>;vs编译表达式。两台不同机器上的反向性能,c#,reflection,lambda,activator,C#,Reflection,Lambda,Activator,我和一位朋友在使用编译表达式而不是Activator.CreateInstance创建对象时进行了测试,得到了一些有趣的结果。我们发现,当我们在每台机器上运行相同的代码时,我们看到的结果完全相反。他得到了预期的结果,编译后的表达式的性能显著提高,而我惊讶地看到Activator.CreateInstance的性能提高了2倍 这两台计算机都是在.NET4.0中编译的 计算机1已安装.NET 4.5。计算机2没有 计算机1超过100000个对象: 45ms - Type<Test>.Ne
Activator.CreateInstance
创建对象时进行了测试,得到了一些有趣的结果。我们发现,当我们在每台机器上运行相同的代码时,我们看到的结果完全相反。他得到了预期的结果,编译后的表达式的性能显著提高,而我惊讶地看到Activator.CreateInstance
的性能提高了2倍
这两台计算机都是在.NET4.0中编译的
计算机1已安装.NET 4.5。计算机2没有
计算机1超过100000个对象:
45ms - Type<Test>.New()
19ms - System.Activator.CreateInstance<Test>();
13ms - Type<Test>.New()
86ms - System.Activator.CreateInstance<Test>();
45ms-Type.New()
19ms-System.Activator.CreateInstance();
计算机2超过100000个对象:
45ms - Type<Test>.New()
19ms - System.Activator.CreateInstance<Test>();
13ms - Type<Test>.New()
86ms - System.Activator.CreateInstance<Test>();
13ms-Type.New()
86ms-System.Activator.CreateInstance();
代码如下:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;
namespace NewNew
{
class Program
{
static void Main(string[] args)
{
Stopwatch benchmark = Stopwatch.StartNew();
for (int i = 0; i < 100000; i++)
{
var result = Type<Test>.New();
}
benchmark.Stop();
Console.WriteLine(benchmark.ElapsedMilliseconds + " Type<Test>.New()");
benchmark = Stopwatch.StartNew();
for (int i = 0; i < 100000; i++)
{
System.Activator.CreateInstance<Test>();
}
benchmark.Stop();
Console.WriteLine(benchmark.ElapsedMilliseconds + " System.Activator.CreateInstance<Test>();");
Console.Read();
}
static T Create<T>(params object[] args)
{
var types = args.Select(p => p.GetType()).ToArray();
var ctor = typeof(T).GetConstructor(types);
var exnew = Expression.New(ctor);
var lambda = Expression.Lambda<T>(exnew);
var compiled = lambda.Compile();
return compiled;
}
}
public delegate object ObjectActivator(params object[] args);
public static class TypeExtensions
{
public static object New(this Type input, params object[] args)
{
if (TypeCache.Cache.ContainsKey(input))
return TypeCache.Cache[input](args);
var types = args.Select(p => p.GetType());
var constructor = input.GetConstructor(types.ToArray());
var paraminfo = constructor.GetParameters();
var paramex = Expression.Parameter(typeof(object[]), "args");
var argex = new Expression[paraminfo.Length];
for (int i = 0; i < paraminfo.Length; i++)
{
var index = Expression.Constant(i);
var paramType = paraminfo[i].ParameterType;
var accessor = Expression.ArrayIndex(paramex, index);
var cast = Expression.Convert(accessor, paramType);
argex[i] = cast;
}
var newex = Expression.New(constructor, argex);
var lambda = Expression.Lambda(typeof(ObjectActivator), newex, paramex);
var result = (ObjectActivator)lambda.Compile();
TypeCache.Cache.Add(input, result);
return result(args);
}
}
public class TypeCache
{
internal static IDictionary<Type, ObjectActivator> Cache;
static TypeCache()
{
Cache = new Dictionary<Type, ObjectActivator>();
}
}
public class Type<T>
{
public static T New(params object[] args)
{
return (T)typeof(T).New(args);
}
}
public class Test
{
public Test()
{
}
public Test(string name)
{
Name = name;
}
public string Name { get; set; }
}
}
使用系统;
使用System.Collections.Generic;
使用系统诊断;
使用System.Linq;
使用System.Linq.Expressions;
名称空间NewNew
{
班级计划
{
静态void Main(字符串[]参数)
{
秒表基准=Stopwatch.StartNew();
对于(int i=0;i<100000;i++)
{
var result=Type.New();
}
benchmark.Stop();
Console.WriteLine(benchmark.elapsedmillesons+“Type.New()”);
基准=秒表.StartNew();
对于(int i=0;i<100000;i++)
{
System.Activator.CreateInstance();
}
benchmark.Stop();
WriteLine(benchmark.elapsedmillesons+“System.Activator.CreateInstance();”;
Console.Read();
}
静态T创建(参数对象[]参数)
{
var types=args.Select(p=>p.GetType()).ToArray();
var ctor=typeof(T).GetConstructor(types);
var exnew=Expression.New(ctor);
var lambda=表达式.lambda(exnew);
var compiled=lambda.Compile();
编制报表;
}
}
公共委托对象ObjectActivator(参数对象[]args);
公共静态类类型扩展
{
公共静态对象新建(此类型输入,参数对象[]args)
{
if(TypeCache.Cache.ContainsKey(输入))
返回TypeCache.Cache[input](args);
var types=args.Select(p=>p.GetType());
var constructor=input.GetConstructor(types.ToArray());
var paraminfo=constructor.GetParameters();
var paramex=Expression.Parameter(typeof(object[]),“args”);
var argex=新表达式[paraminfo.Length];
for(int i=0;i
至少有两个原因:
- 第一次调用
或Type.New()
的开销相对较大。因此,我将100000改为10000000System.Activator.CreateInstance()
- 在发布模式下构建应用程序,在不使用调试器的情况下运行它
Activator.CreateInstance()
只能调用默认构造函数,而您的New()
接受许多参数。如果您降低了New()
的功能,并且始终使用默认构造函数,那么它比我的系统上的Activator.CreateInstance()
稍微快一点
还请注意,如果根据传递的参数使用两个相同类型的不同构造函数,则使用参数处理构造函数实际上不起作用。您只需选择一次用于整个程序其余部分的构造函数。顺便说一句,使用秒表是一种更好的方法。;没有答案,但您不需要字典缓存来完成所有这些。C#静电为你做。看见