分配多个小块比分配一个大块更快/可靠吗?

3
我有一个程序,其中我分配多个缓冲区作为接收队列的一部分,以从端口(UDP协议)接收消息。目前,这些缓冲区不是连续的,但现在我正在考虑使它们连续,以便在需要时可以轻松地将它们拼接在一起。请求1个大内存块而不是重复分配较小的块是否会更不可靠/慢一些呢?
我要考虑的总大小是1000个2KB缓冲区,即2MB。
顺便说一下,我正在使用c++并使用VS2005进行编译,请不要告诉我应该使用TCP,如果我能那样做,我就会使用了。

很难想出一种方法使“删除”代码成为可靠性问题。未编写的代码保证零错误。但是,不要轻易改动已经运行良好的代码。 - Hans Passant
最好是获得一个大请求,只要它们都在同一点范围内,这样可能更可靠。 - Mooing Duck
1000个2KB缓冲区=2048000字节,2MB=2097152字节。 - LihO
这似乎是一个类似的问题:https://dev59.com/Sk7Sa4cB1Zd3GeqP2EIt 我会使用像BOOST这样的经过验证的解决方案。 - Pablo D.
@HansPassant 我担心在系统内存紧张且找不到连续2MB长的块的情况下,它的可靠性会降低,因此我认为分配多个较小的块可能更可靠。我说的不是代码的实际可靠性,而是其操作的可靠性。 - Ian
显示剩余2条评论
5个回答

4

分配一个大块通常比分配多个小块更快。每次分配都有开销,因此使用一个大的分配一次性支付开销而不是多次。


3

1000次分配并不算太糟糕,但当达到1000000时,会出现非常丑陋的开销。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main ()
{
    int i;
    void* bigPtr;
    void* ptrArray[1000];

    clock_t t1, t2, t3;

    t1 = clock();
    for (i = 0; i < 1000; ++i)
    {
        ptrArray[i] = malloc(2048);
    }
    t2 = clock();

    bigPtr = malloc(i*2048);

    t3 = clock();

    printf("1 big allocation: %.0f ms, %i small allocations = %.0f ms\n",
        difftime(t3, t2), i, difftime(t2, t1));

    return 0;
}

输出:

1 big allocation: 0 ms, 1000 small allocations = 2 ms
1 big allocation: 0 ms, 10000 small allocations = 9 ms
1 big allocation: 0 ms, 100000 small allocations = 80 ms
1 big allocation: 0 ms, 1000000 small allocations = 733 ms

3

相比于分配许多小块,分配单个大块肯定更快。然而,它也有自己的缺点。当您分配小块时,很明显知道哪个请求拥有哪个块。完成后,您释放该小块。

如果您分配一个大块,则需要实现某种分配方案,以将大块的范围保留给您的请求,并在完成后将其添加回空闲池中。因此,在这个领域会有一些额外的开销。如果您有其他要求(如您所提到的,将一些请求拼接起来需要为多个请求保留连续的区域),那么您还需要在您的自定义分配器中实现这些功能。因此,您将向代码中添加一定程度的复杂性(和错误)。


1

当然,这样会更快,因为需要进行的分配/释放操作较少。只要最大分配大小在分配器的限制范围内(2MB是在范围之内),我想不出任何原因会使其更可靠或不可靠。


1

自定义分配器在处理大量小对象时可能更快,但对于大对象(小对象数组应该属于此类),则不太可能。它们并不是为了分配大量小对象而设计的。

我不确定是否期望 uint8_t 缓冲区在自定义分配器上分配速度会快上一个数量级。

我不认为替换分配器会更可靠。你正在替换已被证明有效的东西。

如果你有固定的内存量,你可能只想预先分配所有内容,并在需要时将值复制进去。我认为这是避免这种瓶颈的更简单的解决方案。

假设这是一个瓶颈。你进行了性能分析吗?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接