实现简单内存池的 C 库

标签 c multithreading memory memory-management

我注意到我正在开发的应用程序(顺便说一句,用 C 语言编写)充满了 realloc 调用,这些调用由多个线程并行执行。我想要让它更快的是使用内存池,这样我就可以以非常快的方式扩展原始数组。但是,我不想创建自己的内存池,我只想使用线程安全的库(或允许多个线程同时创建池)并支持重新分配。

我在这里查看了之前关于同一问题的问题,但他们未能提供最终的解决方案。例如:

Here有人问了同样的问题,但只建议使用 Apache 运行系统(Hoard 是不同的),但这就像使用火箭筒杀死蚊子。我需要一些简单的东西。

Here所提出的解决方案对我来说太简单了,因为我需要有效的重新分配(如果可能的话,在内存中连续扩展 block )。

重要:显然,许多人认为运算符(operator)没有进行任何类型的分析,只是来这里提出问题。我花了一周的时间分析我的代码,我知道现在对于我的代码来说,reallocs 是多么痛苦。所以,如果你知道如何回答这个问题,那就是我所需要的。

最佳答案

您正在寻找的似乎是一个可调整大小的内存池。不幸的是,内存池是为固定数量的内存而设计的;这就是他们最大限度地减少对malloc的调用的方法。 , realloc

最后,您可能最好看看不同的东西 malloc实现(要考虑的是 Google 的 TCMalloc ;它是 gperftools project 的一部分)而不是内存池,尽管它是 C++。如果您确定需要池,Boost's Pool library值得研究。您也许能够围绕 TCMalloc 创建一个 C 包装器,但我对 boost::pool 不太确定。

如果您想坚持严格使用 C,并且您提前知道要分配什么,您可以创建一个可调整大小的自定义类型,这将有助于优化您的 mallocrealloc来电。您可以使用简单的数组来做到这一点,例如:

typedef struct {
    void *bytes; /* Pointer to the allocated _bytes_. */
    size_t n;    /* The number of _bytes_ used. */
    size_t max;  /* The number of _bytes_ allocated. */
} array;

max始终是 2 的某个幂的最小值,并且在使用一定数量的内存之前,它始终是 2 的幂。那么它总是 2 的倍数以避免占用太多内存,并且 n <= max永远都是真的。这是一个非常简单的观点,但总的来说是个好主意。每当您需要调整数组大小时,不要调用 realloc ,你检查是否需要调用realloc首先使用您自己的函数,或者您是否可以增加使用的字节数(在本例中为 n )。这是一个通用的实现,可以很好地与标准库函数(如 memcpy)配合使用。等等任何数据类型。您可能需要一个专门的表格,例如 int :

typedef struct {
    int *ptr;    /* Pointer to the allocated _items_. */
    size_t n;    /* Number of _items_ used. */
    size_t max;  /* Number of _items_ allocated. */
} int_array;

这和 malloc 之间的区别实现:malloc旨在处理未知类型的未知数量的内存,这意味着未知的大小。这里的负担落在您身上,以保持数组中存储的每个对象的类型或至少大小一致。否则,您将出现未定义的行为。*这使您能够以合理乐观的方式调整分配的内存大小。

我要说一件事:我根本不确定这是否会真正提高你的表现,因为它重复了 malloc 的工作。大多数情况下的实现。 TCMalloc,假设你将它与这个想法结合起来,从大约 6 MB 的内存最大值开始,然后从那里开始增长,可能是 2 的倍数,也可能是 8 的幂。我还没有如此深入地检查源代码,所以我不确定。

* 根据 ISO C,如果您尝试存储 4 字节 int,从技术上讲,您将出现未定义的行为。 4 字节 float无论如何,但这就是为什么您不应该混合类型,即使它们大小相同。

关于实现简单内存池的 C 库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29062687/

相关文章:

c - 猜谜游戏的程序输出不正确

c - 学习 C 试图通过函数找出这个 malloc 的东西

c - "realloc(): Invalid pointer"错误

c++ - 在新建和删除操作中花费了意外的时间

条件变量线程同步

c - 如何将具有多个源子目录的 Make 和 Autotools 项目迁移到 CMake?

c - 在多个源文件中声明一个变量

multithreading - 这是在 Delphi 6 中设置线程名称的正确方法吗?

multithreading - ThreadPoolExecutor 与 threading.Thread

当超过 250 个并发连接时,Ruby SSL TCP 服务器卡住