【问题标题】:What are the pros and cons of using dynamic array of records vs. TList<TMyRecord> in Delphi?在 Delphi 中使用动态记录数组与 TList<TMyRecord> 的优缺点是什么?
【发布时间】:2014-04-08 12:44:16
【问题描述】:

这是一个理论问题,旨在生成 Delphi 中不同数据存储方式的优缺点的查找列表。

假设我们有一个记录:

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

存储此类记录数组的基本选项是:

  • array of TMyRecord;
  • 使用 getter/setter 自定义 TList 的后代
  • TList&lt;TMyRecord&gt;;

我对 #1 与 #3 的比较特别感兴趣,它们之间的差异有多大,尤其是在性能方面。

【问题讨论】:

  • #2 & #3 基本相同,模板为您定制。使用数组,您可以连续存储您的记录。
  • 其实不是。 TList&lt;T&gt; 操作值而不是指针(与 TList 不同)。

标签: arrays delphi storage record


【解决方案1】:

TList&lt;T&gt; 专业人士:

  • Array 没有用于添加/插入/删除/排序/搜索的有用方法,但 TList 有。
  • TList 具有 Notify 方法,可以重写该方法以对项目添加/删除执行一些自定义操作。

TList&lt;T&gt; 缺点:

  • TList&lt;T&gt;[i] 实际上返回其元素的副本。所以你不能写像TList&lt;TMyRec&gt;[idx].SomeField := foo这样的东西。相反,您必须使用临时变量。数组显然允许这样的表达。 David Heffernan 提到了TList&lt;T&gt;.List,它消除了这个缺点;但是,它只出现在 XE3 中
  • TList 是一个对象,在不需要时应该在程序完成时删除
  • System.Generics.Collections 单元可以为之前未使用 System.Classes 单元的项目添加大量二进制大小。

我为我自己编写了TRecordList&lt;T&gt; 类,它将项目作为指针进行操作(就像经典的 TList 一样)。

【讨论】:

  • TList&lt;T&gt;.List 是 dyn 数组,所以不需要副本。在性能方面,dyn 数组没有优势。
  • 你的TRecordList&lt;T&gt; 不适合缓存吗?
  • “程序完成时删除”...实际上应该在超出范围或不再使用时将其删除/释放。
  • 确实,如果你等到程序结束,那么释放它根本没有多大意义,因为系统会收回它。
  • @David Heffernan:感谢提及TList&lt;T&gt;.List,它仅在 XE3 中添加,而我仍在 XE2 上。 @jpfollenius,你肯定是对的。 @David Heffernan:也许这对缓存不利,但对项目插入/排序等有好处。
【解决方案2】:

tl;dr

  • 指向独立内存块的指针列表对缓存不友好,应避免使用。
  • 动态阵列具有与TList&lt;T&gt; 相同的性能特征。
  • TList&lt;T&gt; 为程序员提供了许多动态数组无法提供的便利。

TList&lt;T&gt; 的实现是将项目存储在一个动态数组中。所以TList&lt;T&gt;TArray&lt;T&gt; 之间基本上没有性能差异。

当然,动态数组可以让您直接访问元素而无需进行复制。如果这很重要,您可以使用TList&lt;T&gt;List 属性执行相同的操作。事实上,该属性意味着在性能方面至少TList&lt;T&gt; 与普通动态数组匹配。

除了性能之外,使用TList&lt;T&gt; 为您提供了比原始动态数组更方便的各种便利。我不需要列举这些便利。您可以从公共方法和属性列表中清楚地看到它们。

由于性能对您很重要,因此您应该使用问题中的代码解决真正的性能问题。即您打包记录的事实。这将导致记录的大多数实例未对齐。这对性能有可怕的影响。如果您关心性能,您将调整结构。

您的中间选项,指针列表并不值得考虑。它可能会将内存分散到整个地址空间并且对缓存不友好。

【讨论】:

  • 当我在第一行提到,这是理论上的问题还是不是我的代码(之前你提出了暗示)——我的意思就是这样。代码 sn-p 只是一个示例。我不知道你从哪里读到我有性能问题%)
  • @Krom 我回答的问题,在你改变它之前,有一个打包的记录。由于未对齐,它们的性能很差。如果我忽略这一点,那就太失职了。尤其是因为您要比较的两件事具有相同的性能,因为它们基本上只是数组。对他们来说,性能真的不能更好。我回答的问题中唯一的性能问题是打包数组。如果你有错位是一个大问题。
  • 你可以自己判断对齐有没有问题。在你的代码库中搜索打包。
  • packed 值得评论,我很感谢你这样做。但是,我的主要问题是关于 #1-#3 之间的使用和性能差异,因为 其他一切都相同(打包或不打包)。谢谢
  • 很好。我也已经回答过了。性能没有区别。
猜你喜欢
  • 2020-08-08
  • 1970-01-01
  • 2011-08-13
  • 1970-01-01
  • 2011-03-06
  • 2013-09-17
  • 2010-12-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多