Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.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
.net System.Activator.CreateInstance(T)的性能问题是否足以阻止我们随意使用它?_.net_Performance_Instantiation_Activator - Fatal编程技术网

.net System.Activator.CreateInstance(T)的性能问题是否足以阻止我们随意使用它?

.net System.Activator.CreateInstance(T)的性能问题是否足以阻止我们随意使用它?,.net,performance,instantiation,activator,.net,Performance,Instantiation,Activator,System.Activator.CreateInstance(T)方法是否存在性能问题(因为我怀疑它使用反射),足以阻止我们随意使用它?这取决于您的用例。如果您需要非常高的性能并且正在创建许多对象,那么使用Activator.CreateInstance可能会有问题 但在大多数情况下,它将足够快,是一种非常强大的创建对象的方法 事实上,大多数IoC容器/服务定位器/无论您如何称呼它们,都使用此方法来创建您请求的类型的对象 如果您担心性能不够好,那么应该对应用程序进行分析,并测量是否存在瓶颈以及

System.Activator.CreateInstance(T)
方法是否存在性能问题(因为我怀疑它使用反射),足以阻止我们随意使用它?

这取决于您的用例。如果您需要非常高的性能并且正在创建许多对象,那么使用
Activator.CreateInstance
可能会有问题

但在大多数情况下,它将足够快,是一种非常强大的创建对象的方法

事实上,大多数IoC容器/服务定位器/无论您如何称呼它们,都使用此方法来创建您请求的类型的对象


如果您担心性能不够好,那么应该对应用程序进行分析,并测量是否存在瓶颈以及瓶颈所在。我的猜测是,调用Activator.CreateInstance将不是您的问题。

一如既往,回答性能问题的唯一正确方法是实际测量代码

下面是一个示例程序,用于测试:

  • Activator.CreateInstance
  • 新T()
  • 调用调用新T()的委托
和往常一样,对性能程序持保留态度,这里可能有一些错误会影响结果

输出(计时值以毫秒为单位):


是的,两次呼叫之间存在性能差异

(MyClass)Activator.CreateInstance(typeof(MyClass));

后者的速度更快。但是速度下降是否足够大取决于你的领域。在90%的情况下,这不是一个问题。还要注意的是,对于值类型,
Activator.CreateInstance
由于涉及到

但这里有一个问题:对于泛型类型,它们是相似的
newt()
内部调用
Activator.CreateInstance()
,后者依次调用。因此,如果您有一个通用方法来创建
T
的新实例,那么它应该无关紧要,尽管有
new()
约束并调用
new T()
更具可读性。以下是Jon Skeet的主题。

这是一个C#NET 4.0示例程序,它测试:

  • Activator.CreateInstance
  • 新T()
  • 调用调用新T()的委托
  • 通用新()
  • Activator.CreateInstance使用泛型
  • Activator.CreateInstance使用通用和非默认绑定(例如调用内部构造函数)
输出(时间值以毫秒为单位,来自2014 beefy机器,采用x86版本构建):

Test1-Activator.CreateInstance():8542
Test2-新的T()1082
Test3-委托1214
Test4-泛型new()8759
测试5-通用激活剂9166
Test6-带绑定的通用激活器60772
基线322
这是从Lasse V.Karlsen的回答中采纳的,但重要的是包括泛型。请注意,指定绑定会将使用泛型的Activator的速度降低6倍以上

using System;
using System.Reflection;
using System.Diagnostics;

namespace ConsoleApplication1
{
    public class TestClass
    {
    }

    class Program
    {
        static void Main(string[] args)
        {
            const int IterationCount = 100000000;

            // warmup
            Test1();
            Test2();
            Test3();
            Test4<TestClass>();
            Test5<TestClass>();
            Test6<TestClass>();

            // profile Activator.CreateInstance<T>()
            Stopwatch sw = Stopwatch.StartNew();
            for (int index = 0; index < IterationCount; index++)
                Test1();
            sw.Stop();
            Console.WriteLine("Test1 - Activator.CreateInstance<T>(): {0}", sw.ElapsedMilliseconds);

            // profile new T()
            sw.Restart();
            for (int index = 0; index < IterationCount; index++)
                Test2();
            sw.Stop();
            Console.WriteLine("Test2 - new T() {0}", sw.ElapsedMilliseconds);

            // profile Delegate
            sw.Restart();
            for (int index = 0; index < IterationCount; index++)
                Test3();
            sw.Stop();
            Console.WriteLine("Test3 - Delegate {0}", sw.ElapsedMilliseconds);

            // profile generic new()
            sw.Restart();
            for (int index = 0; index < IterationCount; index++)
                Test4<TestClass>();
            sw.Stop();
            Console.WriteLine("Test4 - Generic new() {0}", sw.ElapsedMilliseconds);

            // generic Activator without bindings
            sw.Restart();
            for (int index = 0; index < IterationCount; index++)
                Test5<TestClass>();
            sw.Stop();
            Console.WriteLine("Test5 - Generic activator {0}", sw.ElapsedMilliseconds);

            // profile Activator with bindings
            sw.Restart();
            for (int index = 0; index < IterationCount; index++)
                Test6<TestClass>();
            sw.Stop();
            Console.WriteLine("Test6 - Generic activator with bindings {0}", sw.ElapsedMilliseconds);


            // profile Baseline
            sw.Restart();
            for (int index = 0; index < IterationCount; index++)
                TestBaseline();
            sw.Stop();
            Console.WriteLine("Baseline {0}", sw.ElapsedMilliseconds);
        }

        public static void Test1()
        {
            var obj = Activator.CreateInstance<TestClass>();
            GC.KeepAlive(obj);
        }

        public static void Test2()
        {
            var obj = new TestClass();
            GC.KeepAlive(obj);
        }

        static Func<TestClass> Create = delegate
        {
            return new TestClass();
        };

        public static void Test3()
        {
            var obj = Create();
            GC.KeepAlive(obj);
        }

        public static void Test4<T>() where T : new()
        {
            var obj = new T();
            GC.KeepAlive(obj);
        }

        public static void Test5<T>()
        {
            var obj = ((T)Activator.CreateInstance(typeof(T)));
            GC.KeepAlive(obj);
        }

        private const BindingFlags anyAccess = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;

        public static void Test6<T>()
        {
            var obj = ((T)Activator.CreateInstance(typeof(T), anyAccess, null, null, null));
            GC.KeepAlive(obj);
        }

        static TestClass x = new TestClass();
        public static void TestBaseline()
        {
            GC.KeepAlive(x);
        }
    }
}
使用系统;
运用系统反思;
使用系统诊断;
命名空间控制台应用程序1
{
公共类TestClass
{
}
班级计划
{
静态void Main(字符串[]参数)
{
常量int迭代计数=100000000;
//热身
Test1();
Test2();
Test3();
Test4();
Test5();
Test6();
//profile Activator.CreateInstance()
秒表sw=Stopwatch.StartNew();
for(int index=0;index(MyClass)Activator.CreateInstance(typeof(MyClass));
new MyClass();
Test1 - Activator.CreateInstance<T>(): 8542
Test2 - new T() 1082
Test3 - Delegate 1214
Test4 - Generic new() 8759
Test5 - Generic activator 9166
Test6 - Generic activator with bindings 60772
Baseline 322
using System;
using System.Reflection;
using System.Diagnostics;

namespace ConsoleApplication1
{
    public class TestClass
    {
    }

    class Program
    {
        static void Main(string[] args)
        {
            const int IterationCount = 100000000;

            // warmup
            Test1();
            Test2();
            Test3();
            Test4<TestClass>();
            Test5<TestClass>();
            Test6<TestClass>();

            // profile Activator.CreateInstance<T>()
            Stopwatch sw = Stopwatch.StartNew();
            for (int index = 0; index < IterationCount; index++)
                Test1();
            sw.Stop();
            Console.WriteLine("Test1 - Activator.CreateInstance<T>(): {0}", sw.ElapsedMilliseconds);

            // profile new T()
            sw.Restart();
            for (int index = 0; index < IterationCount; index++)
                Test2();
            sw.Stop();
            Console.WriteLine("Test2 - new T() {0}", sw.ElapsedMilliseconds);

            // profile Delegate
            sw.Restart();
            for (int index = 0; index < IterationCount; index++)
                Test3();
            sw.Stop();
            Console.WriteLine("Test3 - Delegate {0}", sw.ElapsedMilliseconds);

            // profile generic new()
            sw.Restart();
            for (int index = 0; index < IterationCount; index++)
                Test4<TestClass>();
            sw.Stop();
            Console.WriteLine("Test4 - Generic new() {0}", sw.ElapsedMilliseconds);

            // generic Activator without bindings
            sw.Restart();
            for (int index = 0; index < IterationCount; index++)
                Test5<TestClass>();
            sw.Stop();
            Console.WriteLine("Test5 - Generic activator {0}", sw.ElapsedMilliseconds);

            // profile Activator with bindings
            sw.Restart();
            for (int index = 0; index < IterationCount; index++)
                Test6<TestClass>();
            sw.Stop();
            Console.WriteLine("Test6 - Generic activator with bindings {0}", sw.ElapsedMilliseconds);


            // profile Baseline
            sw.Restart();
            for (int index = 0; index < IterationCount; index++)
                TestBaseline();
            sw.Stop();
            Console.WriteLine("Baseline {0}", sw.ElapsedMilliseconds);
        }

        public static void Test1()
        {
            var obj = Activator.CreateInstance<TestClass>();
            GC.KeepAlive(obj);
        }

        public static void Test2()
        {
            var obj = new TestClass();
            GC.KeepAlive(obj);
        }

        static Func<TestClass> Create = delegate
        {
            return new TestClass();
        };

        public static void Test3()
        {
            var obj = Create();
            GC.KeepAlive(obj);
        }

        public static void Test4<T>() where T : new()
        {
            var obj = new T();
            GC.KeepAlive(obj);
        }

        public static void Test5<T>()
        {
            var obj = ((T)Activator.CreateInstance(typeof(T)));
            GC.KeepAlive(obj);
        }

        private const BindingFlags anyAccess = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;

        public static void Test6<T>()
        {
            var obj = ((T)Activator.CreateInstance(typeof(T), anyAccess, null, null, null));
            GC.KeepAlive(obj);
        }

        static TestClass x = new TestClass();
        public static void TestBaseline()
        {
            GC.KeepAlive(x);
        }
    }
}
//Too bad!!!
T someResult = (T)Activator.CreateInstance(
 typeof(T),   
 //parameter
 new object[] {id}
);