Почему простой List <T>кажется медленнее, чем ArrayList? - PullRequest
7 голосов
/ 05 марта 2012

Из любопытства я хотел проверить количество тиков, чтобы сравнить GenericList с ArrayList.

А для кода ниже, когда я проверяю секундомеры, ArrayList кажется быстрее.

Я делаю что-то не так или есть объяснение этому? (Я полагал, что Список может быть намного быстрее)

Код тестирования и вывод ниже :

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));
}

enter image description here

Ответы [ 2 ]

7 голосов
/ 05 марта 2012

Измените вашу тестовую программу, чтобы запускать метод как минимум дважды и игнорировать первый запуск.Результаты вызваны генерацией кода и джитингом для конкретного типа List<Point>.

На моей машине это приводит к следующему выводу:

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

Что в значительной степени соответствует ожиданиям.

5 голосов
/ 05 марта 2012

Вы не устранили первые эффекты выполнения, такие как JIT. Обобщения должны быть скомпилированы один раз для каждого аргумента типа значения.

ArrayList уже предварительно скомпилирован с помощью ngen.

List<T> прекомпилируется только для определенных типов параметров (я читал, что базовые библиотеки создают некоторые из наиболее важных обобщений для общих аргументов, таких как object, bool, int, ...), если таковые имеются. Так что это повлечет за собой единовременную стоимость.

Следует также отметить, что большая часть стоимости производительности ArrayList является косвенной: бокс оказывает большее давление на ГХ и использует больше памяти. Но ваш тест не будет измерять это. Стоимость производства большего количества мусора также зависит от того, сколько других объектов существует, и от времени жизни объектов.

Когда вы пишете тесты, вы должны либо выполнить весь код один раз перед фактическим тестом, либо использовать столько итераций, что затраты на единовременное использование будут незначительными. Также важно использовать сборку релиза и запускать без отладчика .

...