如何评价自定义内存分配器的质量
How to evaluate the quality of custom memory allocator?
在评估内存分配时应该检查哪些特征?
分配和取消分配的性能?简单的压力测试就足够了吗?如何检查分配质量?
例如,我找到了Oracle的malloc测试,但这只是Oracle对问题的看法。这个测试只面向多线程性能。
人们通常如何检查他们的分配器?
只是把更多的注意力放在"如何"上,而不是其他答案似乎要处理的"是什么"上。我是这样做的。
第一步-使比较方法成为可能
确定你看重什么品质。列一个清单,优先排序,最后,制定一个价值函数。
也就是说,在您的视图/案例中,找出哪些度量是最有用的质量指示器。一些好的测量方法可以是分配内存块的平均时间,应用程序的总运行时间(如果适用),平均帧速率,总或平均内存消耗……这完全取决于你想达到什么目标。
然后,创建一个函数,给定测试运行中的这些测量值,该函数将为您提供一个可用于质量度量的值。最简单的情况是简单地为每个测量值确定一个权重因子。这些权重因素应该体现每个度量的重要性,并且如果它们使用不同的单位(例如用纳秒表示平均分配时间,用字节表示平均内存消耗),则应该尝试缩放它们以进行公平比较。
第二步-设备测试场景
这应该尽可能接近实际情况。最好的是您想要使用内存分配器的实际代码,并添加用于计算值函数所需的所有测量的代码。
第三步-测试
编写一堆不同的分配器,并相互测试它们,以及默认的或没有任何分配器(如果适用)。测量所有结果,计算每个结果的值函数,并根据结果对它们进行排序。请记住在执行性能度量时需要考虑的所有不同因素。
第四步-求值并重复
看看不同的解决方案是如何相互比较的。运用一些批判性思维。这些结果是否与您在测试期间对每个分配器的质量的体验相一致?如果结果与你所看到的不相符。
例如,如果一个看起来非常快,总运行时间比其他的少半分钟,得到一个平庸的分数。那是时候审视一下你的方法了。也许你的测量有问题?或者也许你需要重新评估你选择的价值函数……重复步骤1到步骤4,直到结果清晰,并且看起来与您测试它们的实际经验一致。
通常,内存分配器的性能是关于在堆中查找和创建内存块的速度,这取决于被操作的内存块的大小。而且(最近),它在多线程分配的情况下是如何表现的。您可以在以下列表中找到有趣的研究和基准测试:
- ptmalloc -一个多线程malloc实现
- 无锁内存分配器的基准测试 Linux系统库中的动态内存分配器实现基于FreeBSD的可伸缩并发malloc(3)实现
- …可能还有很多人…
我想我的答案不是天才,但是——看情况。
如果你正在编写自定义内存分配器,你可能知道它的特性是什么。如。如果你想让分配器允许你快速分配很多小对象,你真的不关心内存使用开销,你可能应该有不同的测试,然后当你为大对象创建分配器,你想节省尽可能多的内存,即使CPU时间的成本。
压力测试总是好的,因为它可以帮助您找到一些竞争条件,并检查您的分配器是否没有错误,但性能测试取决于您想要实现的目标。
在优化/分析系统中的动态内存分配机制时,应该考虑以下指标:
- 实现开销 -保持分配的内部数据结构的运行需要消耗多少内存。此外,如果这些结构随着时间的推移而增长或预先分配一次(这两种方法都有优缺点,而且都是有效的)。
- 操作效率 -分配/释放内存块所需的时间。这里的分配通常是一个挑战,因为它几乎从来都不是一个常数时间,并且取决于先前分配的内存块的特征。释放块看起来很简单,但如果与内存碎片清理结合使用,则值得进一步注意(此处不涉及)。
- 线程安全与分配本身关系不大,更多地与在系统中使用某种解决方案的决定有关。基本上,如果你没有线程,没有什么好担心的。如果你有线程,确保你的分配在工作时不会被中断。
- 内存碎片 -实际分配的内存布局。这里出现了两个完全矛盾的需求—在缓冲区中找到正确的位置后立即进行分配,或者确保尽可能少地造成碎片。前者更快,而后者更资源友好(也可能更慢)。
- 垃圾收集——这是一个单独的主题,也是一个独立的研究领域,提到它只是为了完整。重要的是要理解,即使您不打算太频繁地释放已分配的内存,GC仍然可以用于帮助分析已分配的内存,为下一次有效的内存分配准备内部数据结构。空闲CPU时间是执行这个家务任务的最佳时间,这是有争议的。然而,这个话题超出了这个问题的范围。
- C++:矢量分配器行为、内存分配和智能指针
- 是否可以使用分配器对象来释放另一个分配器分配的内存?
- 基于浅树的数据结构的内存分配器,用于频繁分配和解除分配
- shared_ptr的删除程序是否存储在自定义分配器分配的内存中?
- STD分配器是否会在堆上动态分配内存?它可以安全地删除内存吗?
- std::unordered_map 在共享内存中使用 boost:::进程间分配器 - 缺点?
- 支持 CUDA 统一内存的系统分配器的操作系统版本
- 分配分配器为多态对象分配内存
- 如何通过分配器分配内存[10] [10]
- 使用 AMD 的 Vulkan 内存分配器时出现链接器错误 (LNK2005)
- 自定义内存分配器示例(需要一些说明)
- 跨共享/静态库集成C++自定义内存分配器
- 带有realloc的自定义池内存分配器
- C++ 分配器在内存不足时使应用程序崩溃
- 复制有状态分配器:标准库分配器语义和内部内存
- 正在重写MSVC++中的内存分配器
- 将运算符new和运算符delete与自定义内存池/分配器一起使用
- 进程间共享内存的非Boost STL分配器
- 如何使用 CUDA 推力执行策略覆盖推力的低级设备内存分配器
- 如何测试分配器是否使用std::allocate进行内存分配