为什么要设计自定义内存管理器?

时间:2019-05-16 11:14:44

标签: c++ c memory memory-management

过去,我曾设计过简单的固定块存储管理器(SM)和通用存储器管理器。在这两种情况下,我都在启动时分配了大量的堆内存,并一次又一次地使用释放的内存,从而避免了频繁调用昂贵的 malloc / new 调用。

如果我谈论的是固定块SM Github link),那么我实际上已经看到了它带来的性能优势。在我的情况下,随机大小分配大约可提高40%。

但是在使用通用内存管理器Github link)(没有内存池)的情况下,我看不到任何明显的性能提升。我唯一看到的收获就是访问内存使用情况统计信息。在性能方面,由于确定空闲块(在分配过程中)和内存在map中的位置(在释放过程中)的开销而导致速度变慢。

所以我的问题是,在什么情况下自定义通用内存分配器会有用?值得付出努力吗?

3 个答案:

答案 0 :(得分:3)

性能不是开发自定义分配器的唯一原因。 其他原因可能包括:

  1. 更好的调试功能
    有一个内存管理器可以帮助定位一些常见的编程错误,例如使用未初始化的内存,访问分配的块之外的内存,两次释放,一次释放后使用,这不是很好吗?但是,一个好的OS内存管理器可能已经可以立即提供所有这些功能。
  2. 施加内存使用配额
    在较大的项目中,您可能会担心内存消耗,尤其是在使用某些第三方模块的情况下。最好不要让恶意模块的所有其他模块都饿死。
  3. 保证分配
    有时您想确保某个关键功能永远不会失败。预分配大量内存并提供自定义分配器可能是所需的步骤之一。
  4. 不受信任的插件后,
  5. 强制执行内存清理
    保护您的应用程序免受与内存猪相同的不健康情况。
  6. 一个独立系统可能根本没有任何内存管理器。 :-)

答案 1 :(得分:2)

通常,构建自定义分配器的最大动机与性能无关。相反,需要在各种系统上运行的程序会运行到不一致和/或不完整的库中。特别是std lib。此外,嵌入式系统上的硬件限制经常要求应用程序在内存使用和管理方面非常小心。这些程序可以运行从汽车中的交流电到飞机上的自动驾驶仪的所有内容。还有一些没有堆栈的系统需要仔细管理堆。这些例子只是冰山一角。将其与基本分配器(例如许多基于堆栈的设计之一)相结合,您将获得非常易于编写,易于维护和高性能的解决方案。编写自己的分配器的另一个原因很简单,就是耗尽内存。当有足够的“可用”内存,但没有足够大的块可以满足请求时,通常会出现此消息。意味着内存在分配器中变得零散。 Google以“ facebook内存分配器”为例。

所有这些程序中的一个共同主题是需要特定于解决方案的内存管理器。这就是为什么有这么多免费提供的管理器的原因。如果没有特定需要,那么没有充分的理由使用malloc / new以外的任何东西。或者,甚至更好地制定一项策略,要求使用智能指针来处理后台的内存分配。使用外部工具可以轻松完成内存配置和统计,这通常是程序员迈向特定于解决方案的内存管理器的第一步。您永远不要以“通用内存管理器”开始,然后再问“我为什么要使用它”。

最后,您对“存储管理器”一词的使用是指范围更广的工具,它们通常管理从短期内存到长期存储与归档的数据。这些工具非常少见,可能非常复杂,并且再次是针对特定需求(例如数据库)的解决方案特定工具。

性能通常是在程序中包含内存管理器的最后一个原因,也就是说,如果内存管理器不能以至少2的倍数执行系统操作,则说明存在严重错误。该程序为经理找到了一个退化的案例,或者经理本身有一个需要解决的问题。

答案 2 :(得分:1)

几乎不需要设计自定义内存管理器。其中有太多这样的东西,以至于大多数人都可以找到一个可用的机架。几年前,我有一个包含解释器的C ++系统。在最初的测试中,它没有我们期望的那么快。分析表明问题出在内存分配上,它出现在字符串类中。我们从互联网上下载了大约二十个内存管理器,并依次尝试了每个内存管理器。我们能够大大提高速度。我们最终使用的内存管理器始终分配大小为2的幂的块,并为每个块大小维护单独的池。

我们发现那里的内存管理器比我们可能测试的要多。