C++ 一个大池还是几个特定类型的池?

C++ 一个大池还是几个特定类型的池?,c++,memory,pool,C++,Memory,Pool,我正在开发一款需要高性能的视频游戏,所以我试图建立一个良好的记忆策略或游戏的一个特定部分,即游戏“模型”部分,即游戏表现 我有一个对象,它包含一个完整的游戏表示,里面有不同的管理者,以按照游戏规则保持表示的一致性。每个游戏实体目前都是由特定类型的工厂生成的,因此我有几个工厂,允许我按照自己的意愿隔离和更改这些实体的内存管理 现在,我正在这两种选择中进行选择: 每种类型都有一个内存池:这将允许真正快速的分配/解除分配和最小的碎片,因为对象池已经知道分配对象的大小。让我烦恼的一件事是有几个像这样的池

我正在开发一款需要高性能的视频游戏,所以我试图建立一个良好的记忆策略或游戏的一个特定部分,即游戏“模型”部分,即游戏表现

我有一个对象,它包含一个完整的游戏表示,里面有不同的管理者,以按照游戏规则保持表示的一致性。每个游戏实体目前都是由特定类型的工厂生成的,因此我有几个工厂,允许我按照自己的意愿隔离和更改这些实体的内存管理

现在,我正在这两种选择中进行选择:

  • 每种类型都有一个内存池:这将允许真正快速的分配/解除分配和最小的碎片,因为对象池已经知道分配对象的大小。让我烦恼的一件事是有几个像这样的池是分开的,可能会使另一个解决方案更有效
  • 拥有一个由一个游戏表示的所有工厂共享的大内存池:(使用类似于boost::pool的东西以及一些适配器函数),这样我就可以将所有游戏对象的内存分配到一起,并且可以为一个我已经知道总大小的游戏分配一位内存(情况并非总是如此)。我不确定它是否比a更好,因为池中可能存在碎片,因为在同一个池中会有不同大小的对象,但对于内存分析和其他问题修复来说,它看起来更容易
  • 现在,我对A有一些真实的经验,所以我对B并没有经验,我想为一个长期项目提供一些关于这些解决方案的建议对于长寿命项目,哪种解决方案似乎更好?为什么?(注意:在这种情况下,确实需要一个池,因为游戏模型也用于游戏编辑,因此会有很多小对象的分配/解除分配)


    <>编辑说明:如果现在还不清楚,我使用C++,我没有考虑到你正在考虑的内存管理器的具体经验,但是这里有一些通用的指导方针:

    • 如果您不希望内存不足,那么选项1将是最好的选择,因为正如您所说的,它很快(比2快?),并且拥有单独的池将更容易发现分配/解除分配/缓冲区问题(假设池管理器具有良好的错误检测能力)
    • 如果内存可能是一个问题(与目标平台通常可用的内存相比,您的游戏将占用大量内存),那么拥有一个大型池将提供更高效的内存使用。此外,如果您无法准确预测每个池的平均和最大内存需求,那么这是一个更好的选择,除非内存管理器可以动态地增长内存池(理想情况下,也可以动态地从池中释放块)。我所看到的2的唯一缺点是速度可能较慢(是这样吗?),而且内存管理中的错误可能更难检测

    通过使用多个池进行开发,但使用单个池进行最终测试和产品发布,您可能会获得两个方面的最佳效果(假设速度相似)。这样,您可以在开发过程中发现分配/管理问题,但仍然可以从潜在的更高效的单个池中获益。

    可能的解决方案之一是介于1和1之间。二,

    对小对象使用池:每个对象大小一个池。在这种情况下,您可以通过在数组中存储指针来轻松查找池

    此外,您还可以为大型对象设置一个池。在这种情况下,碎片化的可能性较小,时间开销也不那么重要,因为大型对象没有被频繁地分配和解除分配


    关于boost::pool的注意事项。在测试boost::pool的性能时,不仅要测试分配,还要测试释放。我经历过
    boost::pool
    boost::fast\u pool
    释放时间可能非常长。我的案例包括在一个池中分配和取消分配不同大小的小对象

    正确答案针对您的问题域。但在我工作的问题领域中,第一个通常是我们选择的领域

    我做实时或近实时代码。主要是音频编辑和播放。在这段代码中,我们通常无法在回放引擎中从堆向下分配内存。大多数情况下,malloc返回的速度足够快,但有时却不够快。这有时很重要

    因此,我们的解决方案是为某些对象使用特定的池,并为其他所有对象使用通用池。特定的池预先分配了一定数量的元素,并作为一个链表(实际上是一个队列)实现,因此分配和释放只需几次指针更新,以及进入和离开关键部分的成本

    作为异常情况的备用方案;当有人需要从一个特殊的池中进行分配,而这个池是空的时,我们将分配一大块通用内存(几个对象),并将其添加到特殊的池中。一旦分配成为特殊池的一部分,在应用程序退出或启动新项目之前,它永远不会返回到常规池


    正确选择特殊池的初始大小和最大大小是优化应用程序的一个重要部分

    您将遇到的一个问题是,STL实现允许假定相同类型的两个分配器是等效的。这就是Boost.Pool只使用一个池的原因(从技术上讲,它为每种类型使用不同的池)。也就是说,在一般情况下,您的分配器不允许有任何非静态成员。如果您正在制作一个视频游戏,并且您知道STL实现没有这个问题,那么不要担心这个问题,但是
    list::splice