有没有办法衡量装箱/拆箱处罚?

Posted

技术标签:

【中文标题】有没有办法衡量装箱/拆箱处罚?【英文标题】:Is there a way to measure boxing/unboxing penalties? 【发布时间】:2010-11-11 14:30:31 【问题描述】:

我正在使用一个使用从System.Collections.CollectionBase 派生的集合的框架。用户一直在抱怨性能,我觉得这些使用非常频繁的集合可能是问题的很大一部分。有没有办法使用工具或分析器或在 IL 中获得一些关于装箱/拆箱处罚的指标?我需要证据来支持对System.Collections.Generic 的推动。我已经尝试过 CLRProfiler,但往往会迷路并且不确定我应该寻找什么。

更新 到目前为止,感谢大家的投入。我知道这可能不是主要瓶颈,但我正在寻找尽可能多的性能杀手的指标。这只是其中之一,不知道它有多大,因此寻找一种方法来测量它。

【问题讨论】:

我很确定性能问题不会是您使用的集合类。阅读一些关于分析和测试的教程。您还可以采用代码的方法并自行执行它们,以测试它们需要多长时间来处理 1,10,100,100000 个元素并测试它是否真的很重要。 我个人怀疑这是瓶颈;特别是它是集合中的结构还是类? 类。其中很多。用得很重。我知道框架的其他问题(有很多很多问题),但我正在尝试收集尽可能多的指标来说服他们升级。 @AJ:如果您的集合是类(引用类型),那么您甚至一开始就没有装箱问题。 【参考方案1】:

虽然出于很多充分的理由我当然鼓励您从非泛型集合转移到泛型集合,但老实说,我怀疑这些集合是否会导致您的性能问题。拳击通常只有在您达到微观水平时才会成为问题,需要在高性能情况下挤出微小的收益。出于 GC 的原因,通常避免它也很好,但在那个领域通常也是次要的。

换句话说:装箱会导致您的用户会注意到的性能问题,这是非常值得怀疑的。

显然,我是在概括地说。在不知道你的具体情况的情况下,我真的不能肯定地说那么多。


编辑:请注意,虽然我怀疑您的问题可能是您使用非泛型集合本身,但我会指出它是 非常重要的类型 集合用于解决给定问题,特别是当集合中的数据量很大时。这里只是几个例子:

如果您基于键执行查找,例如 Dictionary<TKey, TValue> 之类的哈希表将显着优于 List<T>。 如果您正在检查重复项,HashSet<T> 将具有卓越的性能。 如果您正在寻找FIFO(类似队列)的行为,Queue<T> 将具有卓越的性能。 如果您在集合中的随机位置执行插入/删除,LinkedList<T> 将具有卓越的性能。

这些集合应该是任何 .NET 开发人员(实际上是任何开发人员)工具集的一部分。如果您发现自己在使用项目集合的任何地方都使用List<T>(或ArrayList)或类似的数据结构,那可能会再次导致性能问题,尤其是在你的收藏很大。这些并不是我所说的微不足道的性能提升。因此,请注意为您的集合类型做出明智的选择。


但我一般会推荐一个性能分析器,例如ANTS(很好,但不是免费)或EQATEC(也很好免费)。只需在其中一个程序下运行您的应用程序,然后查看您的瓶颈在哪里。我的猜测是您会发现它与您的非通用集合无关。但很自然,我可能是错的。

【讨论】:

对...与数据访问或网络延迟等其他领域相比,使用集合的性能可能很小。 现在玩 EQATEC。非常感谢您的详细回复。 OMG @Dan Tao,如果可以的话,我会 +23。使用 EQATEC 找到了确凿的证据,你是对的,它与拳击无关,而与数据访问有关。谢谢谢谢谢谢。【参考方案2】:

为什么不设置一个快速控制台应用程序来测量各种操作的速度。您可以使用这样的简单方法:

private TimeSpan TimedAction(Action action)

    var timer = new Stopwatch();

    timer.Start();

    action.Invoke();

    timer.Stop();

    return timer.Elapsed;

然后这样称呼它:

var elapsed = TimedAction(() =>
    
        //Do some stuff with your collection here
    );

Console.WriteLine("Elapsed Time: 0", elapsed.TotalMilliseconds);

您应该能够从中收集足够的经验证据,以确定在类似操作下哪个收集更快。项目数、执行的连续操作数等...

然而,正如上面提到的Dan;与数据访问和网络延迟相比,花费在第三方收集上的整体性能可能微不足道。

【讨论】:

【参考方案3】:

@Dan Tao 说的对的就是钱。

在类似的情况下,我发现自己经常做的是this technique,您可以在任何 IDE 下这样做。

所以我知道你想要衡量一个特定的东西,但总的来说,你最关心的是发现性能问题,无论它们在哪里,对吧?

我们就此类问题进行了辩论,但该计划真正花时间在什么方面与此无关。诸如深入地下图书馆 30 层之类的事情,只是为了执行诸如从资源中提取字符串之类的事情,以便可以将它们翻译成不同的语言,而实际上不需要这样做。诸如某人将属性设置为 True 之类的事情会引发一系列通知,其中包括从列表中添加或删除内容、更新树视图控件、创建和销毁窗口、添加/删除选项卡和菜单项等。然后过了一会儿,该属性再次设置为 False,好像没什么大不了的。诸如在网格控件中设置单元格之类的事情,随之而来的是类似的潮汐波。 一般是摇尾巴的狗。

这就是我所说的真正正在发生的事情。当拳击之类的事情成为问题时,样本会显示出来。

【讨论】:

【参考方案4】:

这是你需要的证明。

来自MSDN:

除了类型安全之外,泛型 集合类型通常执行 更适合存储和操作 值类型,因为不需要 将值类型装箱。

请注意,在现实生活中,泛型实际上并没有微软所说的那么快。差异可以忽略不计。

【讨论】:

以上是关于有没有办法衡量装箱/拆箱处罚?的主要内容,如果未能解决你的问题,请参考以下文章

java 啥是拆箱和装箱,拆箱和装箱 嘛用啊???

Java 装箱 拆箱

java装箱跟拆箱解析

Java自动装箱与拆箱

深入剖析Java中的装箱和拆箱

NET中的类型和装箱/拆箱原理