0

我正在用 C 编写一个跨平台共享库。这个库的工作流程是这样的,

lib *handle = lib_init();
result = lib_do_work(handle);
lib_destroy(handle);

通常,用户会在他们的应用程序启动时初始化它,并在应用程序结束时关闭它。lib_do_work()通常在一秒钟内被多次调用。因此,为了避免每次调用的内存分配和释放,我使用了池化机制。有了这个,我要求池返回我需要的结构的实例。如果没有可用的资源,池将返回一个未使用的实例或创建一个新实例。这个新实例也将被添加到池中,以便下次使用。

对我的库的任何 API 调用都以函数调用开始,该函数调用reset_pool()使池中的所有元素再次可用。该池作为lib_destroy()调用的一部分被销毁。在我的测试中,我观察到有时我的池会获得 100000 多个结构实例。

我想知道这是处理内存的好习惯吗?任何帮助都会很棒。

4

2 回答 2

1

正如评论中已经指出的那样,只有分析才能告诉您分配和释放是否是您的应用程序的瓶颈。此外,如果您的系统始终只分配和释放相同大小的对象,那么默认实现可能会执行得相当好。

通常,池通过预先分配块或元素来提供分配优化。该块被分割成单独的元素以满足单独的分配请求。当池耗尽时,分配一个新块。这是一种分配优化,因为减少对库分配器的调用会更便宜。

池分配器还可以帮助减少碎片。如果应用程序分配和释放具有不同生命周期的不同大小的对象,那么碎片的机会就会增加(并且默认分配器中的合并代码必须做更多的工作)。如果为每个不同大小的对象创建一个池分配器,并且每个池块的大小相同,这将有效地消除碎片。

(正如 Felice 指出的那样,还有另一种类型的池,它预先分配了固定数量的内存供应用程序使用,以确保应用程序使用的内存不会超过预配的内存。)

在解除分配时,可以将单个元素放置到空闲列表中。但。您的reset_pool实现可以只遍历块,释放每个块,然后分配一个新块。

以下内容比较简单。它只处理一种元素。POOL_SIZE 需要调整为适合您的应用程序的合理值。假设数据结构如下:

typedef struct element {
    struct element *next;
    /* ... */
} element;

typedef struct pool_block {
    struct pool_block *next;
    struct element block[POOL_SIZE];
} pool_block;

typedef struct element_pool {
    struct pool_block *pools;
    struct element *freelist;
    int i;
} element_pool;

然后,API 看起来像:

void pool_init (element_pool *p) { /* ... */ }

element * pool_alloc (element_pool *p) {
    element *e = p->freelist;
    if (e) p->freelist = e->next;
    else do {
        if (p->i < POOL_SIZE) {
            e = &p->pools->block[p->i];
            p->i += 1;
        } else {
            pool_block *b = pool_block_create();
            b->next = p->pools;
            p->pools = b;
            p->i = 0;
        }
    } while (e == 0);
    return e;
}

element * pool_dealloc (element_pool *p, element *e) {
    e->next = p->freelist;
    p->freelist = e;
}

void pool_reset (element_pool *p) {
    pool_block *b;
    while ((b = p->pools)) {
        p->pools = b->next;
        pool_block_destroy(b);
    }
    pool_init(p);
}
于 2012-07-10T07:47:26.890 回答
1

我不知道它对于您当前的架构是否过于复杂,但通常一个池会限制池化实例的数量,并在所有池化实例都忙时排队请求。

于 2012-07-10T07:49:38.093 回答