Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/amazon-s3/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Activator.CreateInstance<;T>;vs编译表达式。两台不同机器上的反向性能_C#_Reflection_Lambda_Activator - Fatal编程技术网

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()
    System.Activator.CreateInstance()
    的开销相对较大。因此,我将100000改为10000000
  • 在发布模式下构建应用程序,在不使用调试器的情况下运行它
有了这两个变化,这两种方法所需的时间大致相同。在我的系统中,两种方法的值都在1100到1200之间,有时一种稍高一点,有时另一种稍高一点

请注意,
Activator.CreateInstance()
只能调用默认构造函数,而您的
New()
接受许多参数。如果您降低了
New()
的功能,并且始终使用默认构造函数,那么它比我的系统上的
Activator.CreateInstance()
稍微快一点


还请注意,如果根据传递的参数使用两个相同类型的不同构造函数,则使用参数处理构造函数实际上不起作用。您只需选择一次用于整个程序其余部分的构造函数。

顺便说一句,使用秒表是一种更好的方法。;没有答案,但您不需要字典缓存来完成所有这些。C#静电为你做。看见