【问题标题】:How to evaluate the quality of custom memory allocator?如何评估自定义内存分配器的质量?
【发布时间】:2013-04-12 13:16:42
【问题描述】:

评估内存分配时应该检查哪些特征?

分配和取消分配的性能?简单的压力测试就足够了吗?如何检查分配的质量?

例如,我找到了 Oracle 对malloc 的测试,但这只是 Oracle 对问题的看法。而且这个测试只针对多线程性能。

人们通常如何检查他们的分配器?

【问题讨论】:

  • 您必须首先决定您希望自定义分配器解决哪些问题。您只是想要更快的内存分配吗?您是否进行大量可预测大小的分配?您是否在内存有限的平台上编写长时间运行的应用程序,这意味着碎片是一个问题?
  • 这是否意味着分配器应该只从一个角度检查?只为了速度?只为了碎片化?等等?
  • 对不起,不,我根本不是故意的。我见过的大多数分配器测试都集中在速度上。如果您正在编写一个 linux 桌面库,那么这可能就是您所关心的。如果您正在编写一些不太常见的东西,则需要确定有多少不同(通常是相互冲突的)用例对您很重要,并相应地寻找或设计测试。

标签: c++ c testing memory-management


【解决方案1】:

以下是优化/分析系统中的动态内存分配机制时应考虑的指标。

  • 实施开销 - 保持分配的内部数据结构正常运行需要多少内存。此外,如果这些结构随着时间的推移而增长或预先分配一次(这两种方法都有利有弊,并且都有效)。
  • 操作效率 - 分配/释放内存块需要多长时间。在这里,分配通常是一个挑战,因为它几乎从来都不是一个恒定的时间,并且取决于先前分配的内存块的特性。释放块看起来很简单,但如果与内存碎片整理结合使用,则值得进一步关注(此处不再介绍)。
  • 线程安全与分配本身的关系不大,而与在系统中使用某些解决方案的决定有关。基本上在这里,如果你没有线程 - 没有什么可担心的。如果您确实有线程,请确保您的分配在工作时不会被中断。
  • 内存碎片 - 分配内存的实际布局。这里有两个完全矛盾的要求在起作用——一旦在缓冲区中找到正确的位置就进行分配,或者确保尽可能少地产生碎片。前者速度快,而后者对资源更友好(也可能更慢)。
  • 垃圾收集 - 这是一个单独的主题和一个独立的研究领域,只是为了完整起见才提到它。重要的是要理解,即使您不打算经常释放分配的内存,GC 仍然可以用于帮助分析已分配的内存,为下一次有效的内存分配准备内部数据结构。可以说,空闲 CPU 时间是执行此管家任务的最佳时机。但是,此主题超出了此问题的范围。

【讨论】:

    【解决方案2】:

    通常,内存分配器的性能与在堆中查找和创建内存块的速度有关,具体取决于操作的内存块的大小。而且,(但最近),它在多线程分配的情况下是如何表现的。您可以在以下列表中找到有趣的研究和基准:

    【讨论】:

      【解决方案3】:

      只是为了更加关注“如何”,而不是“什么”,其他答案似乎都在处理。以下是我的做法。

      第一步 - 让比较方法成为可能

      确定你看重的品质。列出清单,确定优先级,最后制定价值函数。

      也就是说,在您的观点/案例中,找出哪些测量是最有用的质量指标。一些好的测量可能是分配内存块的平均时间、应用程序的总运行时间(如果适用)、平均帧速率、总或平均内存消耗......这一切都取决于您希望实现的目标。

      然后,创建一个函数,根据测试运行的这些测量值,该函数会为您提供一个可用作质量测量值的值。最简单的情况是简单地为每个测量确定一个权重因子。这些权重因子应该体现每次测量的重要性,如果它们使用不同的单位(例如平均分配时间的纳秒和平均内存消耗的字节),请尝试对它们进行缩放以进行公平比较。

      第二步 - 设备测试场景

      这应该尽可能接近现实情况。最好的方法是简单地使用您想要使用内存分配器的实际代码,并添加用于进行计算价值函数所需的所有测量的代码。

      第三步 - 测试

      编写一堆不同的分配器并相互测试它们,以及默认或没有任何分配器(如果适用)。测量所有结果,计算每个结果的价值函数并根据结果对它们进行排名。请记住在执行性能测量时始终需要考虑的所有不同注意事项。

      第四步 - 评估和重新迭代

      看看不同的解决方案如何相互叠加。应用一些批判性思维。这些结果是否真的与您在测试期间体验每个分配器的质量相对应?如果结果与您认为看到的不符。

      例如,如果一个看起来非常快并且总运行时间比其他人少半分钟的那个,得到一个平庸的分数。那么,是时候仔细检查你的方法了。也许您的测量中有错误?或者您可能需要重新评估您选择的价值函数...重复步骤 1 到 4,直到结果清晰并且看起来符合您测试它们的实际经验。

      【讨论】:

        【解决方案4】:

        我想我的答案不是天才,但 - 这取决于。

        如果您正在编写自定义内存分配器,您可能知道它的特点。例如。如果您希望分配器允许您快速分配大量小对象并且您并不真正关心内存使用开销,那么当您为大对象创建分配器并且想要节省尽可能多的内存时,您可能应该进行不同的测试即使消耗 CPU 时间也是可能的。

        压力测试总是很好,因为它可以帮助您找到一些竞争条件并检查您的分配器是否没有错误,但性能测试取决于您想要达到的目标。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-05-29
          • 2012-02-22
          • 2014-01-28
          • 1970-01-01
          • 2011-02-14
          • 1970-01-01
          • 2012-07-08
          • 1970-01-01
          相关资源
          最近更新 更多