【问题标题】:Fast access to a (sorted) TList快速访问(排序的)TList
【发布时间】:2011-09-23 08:49:37
【问题描述】:

我的项目(在 Delphi 6 上运行!)需要一个内存分配列表 (TMemoryAllocation),我将其存储在一个对象中,该对象还包含有关分配大小 (FSize) 以及分配是否正在使用或空闲的信息(融合)。我基本上将它用作 GarbageCollector 和一种始终保持分配/解除分配内存应用程序的方法(并且需要大量分配/解除分配)。

每当我的项目需要分配时,它都会查找列表以找到适合所需大小的空闲分配。为此,我使用了一个简单的 for 循环:

for I := 0 to FAllocationList.Count - 1 do
begin
  if MemoryAllocation.FUsed and (MemoryAllocation.FSize = Size) then
...

我的应用程序运行的时间越长,这个列表就会增长到数千个项目,并且当我非常频繁地运行它(每秒几次)时,它的运行速度会大大降低。

我正在努力寻找一种方法来加速这个解决方案。我考虑过按分配大小对 TList 进行排序。如果我这样做了,我应该使用某种智能方式来访问列表,以获得我在每次通话中需要的特定大小。 有什么简单的方法可以做到这一点吗?

我考虑的另一种方法是有两个 TList。一个用于未使用的分配,一个用于已使用的分配。这意味着尽管我必须从一个列表中提取 TList.Items 并一直添加到另一个列表中。而且我仍然需要使用 for 循环来遍历(现在)较小的列表。 这是正确的方法吗?

其他建议也非常欢迎!

【问题讨论】:

  • 您不使用 FastMM 有什么原因吗?从您的描述来看,FastMM 的作用似乎差不多。我认为 FastMM 实际上使用了几个不同大小的分配列表:小( 1024 字节)的列表。
  • 你考虑过使用FastMM吗?
  • 您需要 GarbageCollector 那么您的应用程序是多线程的吗?
  • FastMM 将是 BorlandMM 的一大步。不利的一面是,它在严重的线程争用下挣扎,但这可能不是问题。第一步是尝试 FastMM。
  • 感谢有关 FastMM 的提示!我会试试的。 @GJ:是的,我的应用程序是多线程的。它不完全是 GarbageCollector,而只是类似的。我将内存分配保留在我的列表中以供重用。只有大于 1KiB 的大内存分配会被 GC 函数释放。

标签: delphi delphi-6


【解决方案1】:

你有几种可能:

  • 当然,使用经过验证的内存管理器 FastMM4 或一些 others 专用于更好地扩展多线程应用程序;
  • 重新发明轮子。

如果您的应用程序对内存分配非常敏感,也许有一些关于重新发明轮子的反馈:

  • 利用您的块大小,例如每 16 字节的倍数,然后为每个块大小维护一个列表 - 这样您就可以快速找到好的块“系列”,并且不必将每个单独的块大小存储在内存中(如果它在 32 字节列表中,它是一个 32 字节的块);
  • 如果需要重新分配,请尝试猜测减少内存复制的最佳增加因子;
  • 按大小对块进行排序,然后使用binary search,这将比普通的 for i := 0 to Count-1 循环快得多;
  • 在列表中维护一块已删除的项目,当您需要新项目时可以在其中查找(因此您不必删除该项目,只需将其标记为空闲 - 如果列表很大);
  • 不要使用列表(在删除或插入包含大量项目的已排序项目时会出现一些速度问题),而对于项目和已释放项目,请使用链表。

这绝对不是那么简单,因此您可能需要先查看一些现有的代码,或者只是依赖现有的库。我认为你不必在你的应用程序中编写这个内存分配,除非 FastMM4 对你来说不够快,我会非常怀疑,因为这是一段很棒的代码!

【讨论】:

    猜你喜欢
    • 2012-03-17
    • 2018-01-31
    • 2020-06-18
    • 2020-08-14
    • 2017-01-14
    • 2014-10-10
    • 2016-12-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多