【问题标题】:List perfomance vs ArrayList memory allocation performance列表性能与 ArrayList 内存分配性能
【发布时间】:2015-02-05 12:36:32
【问题描述】:

我有以下代码:

namespace ConsoleCodeGenerator
{
    internal class Foo
    {
        public double F { get; set; }
    }

    internal class Program
    {
        private static void Main(string[] args)
        {
            //int size = 100000;
            int size = 70000000;

            List<Foo> list = new List<Foo>(size);
            ArrayList arrayList = new ArrayList(size);

            Stopwatch sw = new Stopwatch();
            sw.Start();
            for (int i = 0; i < size; i++)
            {
                Foo f = new Foo();
                f.F = i;
                list.Add(f);
            }
            sw.Stop();
            Console.WriteLine("List: {0}", sw.ElapsedMilliseconds);

            Stopwatch sw2 = new Stopwatch();
            sw2.Start();
            for (int i = 0; i < size; i++)
            {
                Foo f = new Foo();
                f.F = i;
                arrayList.Add(f);
            }
            sw2.Stop();
            Console.WriteLine("arrayList: {0}", sw2.ElapsedMilliseconds);
        }
    }
}

如果我使用 int size = 100000;然后 List 以 2:6 毫秒的比例优于 ArrayList。但是如果要使 size = 70000000;然后 ArrayList 在我的计算机上具有更好的性能 5450:4809。看起来处理巨大的(大约数百万个项目)ArrayList 可能比 List 更快。为什么装箱/拆箱在小内存分配中很重要,而在大数组中无关紧要

【问题讨论】:

  • 你的问题是......?
  • 另外,请注意没有装箱/拆箱,因为您没有存储值类型。
  • List&lt;&gt; 在后台使用ArrayList,因此性能应该几乎相同。 List&lt;&gt; 应该有一些额外的指令需要解释,但肉眼看不到
  • 不,它没有使用 ArrayList,它使用了一个数组。检查我之前提到的参考来源。顺便说一句,ArrayList 也一样,它也使用了一个数组。
  • @Areius 我的源参考显示数组列表protected ArrayList InnerList { get { if (list == null) list = new ArrayList(); return list; } }

标签: c# .net list arraylist


【解决方案1】:

你的误解比这更深一点。

首先,制定一个好的基准很难——你的不好。

其次,装箱只发生在值类型上——你在这两种情况下都添加了一个类,所以即使使用ArrayList也不会发生装箱。事实上,通过将 double 包装在一个类中,您只是手动装箱该值 - 这就是装箱的意思(当然,IL box / unbox 指令可能是效率更高一些)。尝试直接插入double,你会看到巨大的不同。

为了扩展基准测试问题,您完全忽略了内存分配(和收集)模式。当您预先分配数组本身时(这就是容量参数的用途),您并没有预先分配对象(Foo)。例如,这对于结构或 doubles 并不重要,但在这种情况下,您只是将所有内存压力推入相关循环。

List 在方法中不再使用时就可以进行收集,因此ArrayList 将在需要收集时立即获得空闲的、预先准备好的内存。所以即使是测试的顺序也会产生很小的差异。

最后,您需要可重复性 - 使用 List 进行一百次测试,使用 ArrayList 进行一百次测试,尽可能隔离。并且不要忘记预热基准以摆脱初始化时间。

您可以找到很多关于在 C# 中进行体面基准测试的信息。真的不容易。

【讨论】:

  • 是的,如果更改为 double 则 List 和 ArrayList 之间的差异是 486: 5107。谢谢
猜你喜欢
  • 1970-01-01
  • 2010-11-23
  • 2018-11-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-26
  • 1970-01-01
  • 2011-01-31
相关资源
最近更新 更多