本文介绍了并System.Activator.CreateInstance(T)有性能问题,大到足以使用它随便阻止我们吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

确实 System.Activator.CreateInstance(T)方法有性能问题(因为我怀疑它使用反射)大到足以使用它随便阻止我们?

Does System.Activator.CreateInstance(T) method have performance issues (since I'm suspecting it uses reflection) big enough to discourage us from using it casually?

推荐答案

与往常一样,唯一正确的方式来回答一个问题,有关性能是实际测量code。

As always, the only correct way to answer a question about performance is to actually measure the code.

下面是一个示例 LINQPad 程序测试:

Here's a sample LINQPad program that tests:

  • Activator.CreateInstance
  • 在新T()
  • 调用委托调用新T()

和往常一样,把演出节目有一粒盐,可能会有错误这里歪斜的结果。

As always, take the performance program with a grain of salt, there might be bugs here that skews the results.

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

The output (timing values are in milliseconds):

Test1 - Activator.CreateInstance<T>() 
12342 

Test2 - new T() 
1119 

Test3 - Delegate 
1530 

Baseline 
578 

请注意,上面的时序是100.000.000(100万美元)建设的对象。开销可能不是你的程序的一个现实问题。

Note that the above timings are for 100.000.000 (100 million) constructions of the object. The overhead might not be a real problem for your program.

警告性的结论将是, Activator.CreateInstance&LT; T&GT; 正在大约11倍多的时间做同样的工作作为一个新款T ()做,并委托需要大约1.5倍。请注意,这里的构造函数什么也不做,所以我只是试图测量的不同方法的开销。

Cautionary conclusion would be that Activator.CreateInstance<T> is taking roughly 11 times as much time to do the same job as a new T() does, and a delegate takes roughly 1.5 times as much. Note that the constructor here does nothing, so I only tried to measure the overhead of the different methods.

编辑:我添加了一个基准通话,不构造对象,但确实的东西休息,定时的为好。与作为基准,它看起来像一个委托花费的时间比一个简单的新(75%以上的时间),以及Activator.CreateInstance需要1100左右%以上。

I added a baseline call that does not construct the object, but does the rest of the things, and timed that as well. With that as a baseline, it looks like a delegate takes 75% more time than a simple new(), and the Activator.CreateInstance takes around 1100% more.

然而,这是微优化。如果你真的需要做到这一点,和伊克出一些时间要求严格的code的每点性能,我想无论是手工codeA委托改为使用,或者如果这是不可能的,即。您需要提供在运行时的类型,我会用Reflection.Emit的动态产生的委托。

However, this is micro-optimization. If you really need to do this, and eek out the last ounce of performance of some time-critical code, I would either hand-code a delegate to use instead, or if that is not possible, ie. you need to provide the type at runtime, I would use Reflection.Emit to produce that delegate dynamically.

在任何情况下,这里是我真正的答案:

In any case, and here is my real answer:

如果您有性能问题,来看看你的瓶颈是第一项措施。是的,上面的时序可能表明Activator.CreateInstance有更多的开销比一个动态构建的委托,但可能有更大的鱼在codeBase的炒之前,你(甚至是必须得到),以优化这一水平

和公正,以确保我确实回答你具体的问题:不,我不会妨碍使用Activator.CreateInstance的。你应该知道,它使用反射,让你知道,如果这顶你分析瓶颈的名单,那么你也许能够做一些事情,但它使用反射的事实并不意味着它的的瓶颈。

And just to make sure I actually answer your concrete question: No, I would not discourage use of Activator.CreateInstance. You should be aware that it uses reflection so that you know that if this tops your profiling lists of bottlenecks, then you might be able to do something about it, but the fact that it uses reflection does not mean it is the bottleneck.

该计划:

void Main()
{
    const int IterationCount = 100000000;

    // warmup
    Test1();
    Test2();
    Test3();
    Test4();

    // profile Activator.CreateInstance<T>()
    Stopwatch sw = Stopwatch.StartNew();
    for (int index = 0; index < IterationCount; index++)
        Test1();
    sw.Stop();
    sw.ElapsedMilliseconds.Dump("Test1 - Activator.CreateInstance<T>()");

    // profile new T()
    sw.Restart();
    for (int index = 0; index < IterationCount; index++)
        Test2();
    sw.Stop();
    sw.ElapsedMilliseconds.Dump("Test2 - new T()");

    // profile Delegate
    sw.Restart();
    for (int index = 0; index < IterationCount; index++)
        Test3();
    sw.Stop();
    sw.ElapsedMilliseconds.Dump("Test3 - Delegate");

    // profile Baseline
    sw.Restart();
    for (int index = 0; index < IterationCount; index++)
        Test4();
    sw.Stop();
    sw.ElapsedMilliseconds.Dump("Baseline");
}

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

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

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

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

TestClass x = new TestClass();
public void Test4()
{
    GC.KeepAlive(x);
}

public class TestClass
{
}

这篇关于并System.Activator.CreateInstance(T)有性能问题,大到足以使用它随便阻止我们吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-30 06:55