Каковы плюсы и минусы использования динамического массива записей против TList в Delphi?

это теоретический вопрос, предназначенный для создания списка плюсов и минусов различных способов хранения данных в Delphi.

допустим, у нас есть запись:

type
  TMyRecord = record 
    X,Y,Z: Single; 
    IsValid: Boolean; 
  end;

основными вариантами хранения массива таких записей являются:

  • array of TMyRecord;
  • пользовательские потомок TList С геттер/сеттер
  • TList<TMyRecord>;

меня особенно интересует сравнение #1 vs #3, Сколько стоит разница между ними, особенно с точки зрения производительности.

2 ответов


TList<T> плюсы:

  • массив не имеет полезных методов для добавления / вставки / удаления / сортировки / поиска, TList делает.
  • TList имеет метод Notify, который может быть переопределен для выполнения некоторых пользовательских действий по добавлению/удалению элемента.

TList<T> плюсы:

  • TList<T>[i] на самом деле возвращает скопировать ее элемент. Поэтому вы не можете написать что-то вроде TList<TMyRec>[idx].SomeField := foo. Вместо этого, вы должны используйте временную переменную. Array явно допускает такое выражение. Дэвид Хеффернан упомянул TList<T>.List что устраняет этот недостаток; однако он появился только в XE3
  • TList-это объект, который должен быть удален на финише программы когда не нужен.

tl; dr

  • список указателей на независимые блоки памяти является недружественным для кэша и его следует избегать.
  • динамические массивы имеют те же характеристики производительности, что и TList<T>.
  • TList<T> предлагает много удобств программисту, которые динамические массивы не позволяют.

реализация TList<T> заключается в том, что элементы хранятся в динамическом массиве. Так есть по существу нет различий в производительности между TList<T> и TArray<T>.

конечно, динамический массив дает вам прямой доступ к элементам без создания копий. Вы можете сделать то же самое, используя List собственность TList<T> Если это имеет значение. На самом деле это свойство означает, что с точки зрения производительности по крайней мере TList<T> соответствует простому динамическому массиву.

за пределами производительности, используя TList<T> дает вам все виды услуг по сырым динамические матрица. Мне не нужно перечислять эти удобства. Вы можете ясно видеть их из списка общедоступных методов и свойств.

поскольку производительность важна для вас, вы должны решить реальную проблему производительности с кодом в вопросе. А именно тот факт, что вы упаковали свой рекорд. Что приведет к большинству экземпляров записи несоосность. И это имеет ужасные последствия для производительности. Если вы заботитесь о производительности, вы выровняете структуры.

ваш средний вариант, список указателей на самом деле не стоит рассматривать. Скорее всего, он разбросает память по всему адресному пространству и будет недружелюбен к кэшу.