【问题标题】:Do I need a custom memory allocator?我需要自定义内存分配器吗?
【发布时间】:2013-05-20 14:38:20
【问题描述】:

我目前正在开发一个缓存服务器,它本身就使用了很多 RAM(我正在一个有很多 HTTP 流量的服务器上测试它,同时有一个 WordPress 和一个自定义网络应用程序使用它来缓存内存中的数据)。

服务器显然执行了很多昂贵的 malloc/realloc/free 操作,所以我想知道是否应该使用自定义内存分配器,也许是在开始时预分配一个大“内存池”然后使用它在执行 malloc/realloc 时提供所需大小的空闲“块”,并在调用 free 时将它们标记为已释放。

我是在走正确的道路还是我真的不需要这样的东西?有没有这样的分配器,还是我必须自己编写一个?

重要提示:

  • 服务器是单线程(使用多路复用),所以我不 在多线程中需要具有高性能等级的分配器 应用程序(例如 jemalloc,据我了解是 与单线程应用程序中的普通 malloc 一样好...... 如果我错了,请纠正我)。

  • 在您询问/建议之前,我已经使用 Valgrind 删除了每个 可能的内存泄漏。我只需要优化,而不是修复。

  • 内存碎片是个问题,所以我也应该使用一种方法来优化它。

  • 使用适当的配置指令,用户可以设置 来自服务器的最大可用内存,这就是预分配的原因 我想到了固定内存池。

  • 我没有性能问题;我开发这个只是为了好玩和好奇。我喜欢学习和尝试新的编程技术。

  • 是的,我使用过 callgrind,而 malloc 是最昂贵的操作之一。

【问题讨论】:

  • "我需要自定义内存分配器吗?"如果你不得不问,答案是“不”。
  • 如果您没有性能问题,为什么要修复未损坏的部分?
  • 因为我开发这个只是为了好玩和好奇,我喜欢学习和试验新的编程技术,所以......为什么不呢? :)
  • +1 凯文的评论。这个问题的答案基本上总是“不”。特别是对于单线程使用,所有现代分配器使用的基本 dlmalloc 算法是无与伦比的
  • @R.. 这不是无与伦比的。它解决的问题肯定是一流的:实现mallocfree,也就是所有人的一切。但是,如果您知道您的内存使用模式并且它足够统一,那么另一种更简单的分配器就足够了(例如:如果您只需要固定大小的块,则使用池;如果您只需要 FIFO 行为,则使用堆栈分配器)然后专门用于该用例很有可能击败*malloc,因为它可以做出*malloc 无法做出的有用假设(并相应地进行优化)。

标签: c memory memory-management


【解决方案1】:

既然你说你没有性能问题,你不需要做任何事情。把它放在一边。

你需要一个立足点来获得任何改进,因为malloc 真的很快。我记得几年前在 Mac OS X 上大约有 100-200 个周期。 (但free 也可能需要更多时间,这应该会显示在分析统计中。)编写一个更好的通用分配器基本上是不可能的,除了技巧和运气。

但是,特定于您的应用程序的模式仍然可以提供机会。我很幸运,程序可以按照与创建对象大致相同的顺序释放对象。

  1. 创建一些内存桶。
  2. malloc 以线性方式从桶中返回块。
  3. free 将块标记为未使用。这可以利用位图、受管理的智能指针等。对于纯垃圾回收,不需要显式调用。
  4. 当最后一个桶已满时,扫描最近使用的最后一个桶,但只检查是否完全为空。
  5. 如果没有空桶,则制作一个新桶。

如果存在 任何 碎片,这是一个可怕的策略,但它可以将普通的 malloc 提高几个数量级,因为沿着存储桶扫描直到结束只需要 1-2 个周期100-200,并且对于足够少的碎片,您总是可以使扫描频率足够低。

百万分之一的慢速扫描也使这种方法无法应用于许多应用程序。

我对缓存服务器了解不多,但也许这种方法适用于高度瞬态的 HTTP 连接对象。您需要关注的不是所有malloc,而是以最可预测的模式产生最大成本的分配子集。

【讨论】:

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