简体   繁体   中英

Why does a simple List<T> seem to be slower than an ArrayList?

Out of curiosity I wanted to test the number of ticks to compare a GenericList against an ArrayList.

And for the below code when I check the stopwatches, ArrayList seems to faster.

Do I make something wrong or is there an explanation for this? (I believed List sto be much faster)

Tesing Code and the output below :

private static void ArrayListVsGenericList()
{
    // Measure for ArrayList
    Stopwatch w0 = new Stopwatch();
    w0.Start();

    ArrayList aList = new ArrayList();

    for (int i = 0; i < 1001; i++)
    {
        Point p = new Point();
        p.X = p.Y = i;

        aList.Add(p);
    }

    foreach (Point point in aList)
    {
        int v0 = ((Point) aList[8]).X; //unboxing
    }


    w0.Stop();

    // Measure for Generic List<Point>
    Stopwatch w1 = new Stopwatch();
    w1.Start();

    List<Point> list = new List<Point>();

    for (int i = 0; i < 1001; i++)
    {
        Point p = new Point();
        p.X = p.Y = i;

        list.Add(p); 
    }


    foreach (var point in list)
    {
        int v1 = list[8].X;
    }

    w1.Stop();

    Console.WriteLine("Watch 0 : " + w0.ElapsedTicks);
    Console.WriteLine("Watch 1 : " + w1.ElapsedTicks);
    Console.WriteLine("Watch 0 > Watch 1 : " + (w0.ElapsedTicks > w1.ElapsedTicks));
}

在此输入图像描述

Change your test program to run your method at least twice and ignore the first run. The results are caused by code generation and jitting for the concrete type List<Point> .

On my machine this leads to the following output:

  Watch 0 : 154
  Watch 1 : 74
  Watch 0 > Watch 1 : True

Which is pretty much what one would expect.

You did not eliminate first execution effects like JIT. Generics need to be compiled once for every value type argument.

ArrayList is already precompiled with ngen.

List<T> is only precompiled for certain parameter types(I read that the core libraries instantiate some of the most important generics for the common arguments, like object, bool, int,...), if at all. So it will incur a one time cost.

You should also note, that most of the performance cost of ArrayList is indirect: The boxing puts higher pressure on the GC, and uses more memory. But your test won't measure that. The cost of producing more garbage also depends on how many other objects exist, and on the lifetime of the objects.

When you write tests, you should either execute all code once before the actual test, or use so many iterations that one time costs are negligible. It's also important to use a release build and run without the debugger attached .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM