glibc posix_memalign分配开销

时间:2016-02-05 21:16:45

标签: glibc

我试图理解与posix_memalign相关的内存开销 - 换句话说,如果posix_memalign依赖于边界标记以及这种标记有多大。

所以我编写了以下(非常简单的)程序(linux x86_64平台,“gcc -m64”):

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

int
main(int argc, char* argv[])
{
    int   i;
    void* prev;
    void* memp;

    int align = atoi(argv[1]);
    int alloc = atoi(argv[2]);

    for (i = 0; i < 5; ++i)
    {
        if (posix_memalign(&memp, align, alloc))
        {
            fprintf(stderr, "allocation failed\n");
            return 1;
        }

        if (i == 0)
            printf("allocated %d bytes at 0x%08x\n", alloc, memp);
        else
            printf("allocated %d bytes at 0x%08x (offset: %d)\n",
                   alloc, memp, (int)(memp-prev));

        prev = memp;
    }

    return 0;
}

然而,结果让我感到困惑......

$ /tmp/test 8 1
allocated 1 bytes at 0x0133a010
allocated 1 bytes at 0x0133a030 (offset: 32)
allocated 1 bytes at 0x0133a050 (offset: 32)
allocated 1 bytes at 0x0133a070 (offset: 32)
allocated 1 bytes at 0x0133a090 (offset: 32)

same for allocations of 2 to 24 bytes, until:

$ /tmp/test 8 25
allocated 25 bytes at 0x0198c010
allocated 25 bytes at 0x0198c040 (offset: 48)
allocated 25 bytes at 0x0198c070 (offset: 48)
allocated 25 bytes at 0x0198c0a0 (offset: 48)
allocated 25 bytes at 0x0198c0d0 (offset: 48)

same for allocations of 26 to 40 bytes, until:

$ /tmp/test 8 41
allocated 41 bytes at 0x0130c010
allocated 41 bytes at 0x0130c050 (offset: 64)
allocated 41 bytes at 0x0130c090 (offset: 64)
allocated 41 bytes at 0x0130c0d0 (offset: 64)
allocated 41 bytes at 0x0130c110 (offset: 64)

所以我最初得出结论,最小分配是32字节,而posix_memalign使用了8字节边界标记。

使用16字节对齐获得了相同的结果。但是32字节对齐的事情很奇怪:

$ /tmp/test 32 1
allocated 1 bytes at 0x0064c040
allocated 1 bytes at 0x0064c080 (offset: 64)
allocated 1 bytes at 0x0064c120 (offset: 160)
allocated 1 bytes at 0x0064c160 (offset: 64)
allocated 1 bytes at 0x0064c200 (offset: 160)

same for allocations of 2 to 24 bytes, until:

$ /tmp/test 32 25
allocated 25 bytes at 0x01e0c040
allocated 25 bytes at 0x01e0c0c0 (offset: 128)
allocated 25 bytes at 0x01e0c140 (offset: 128)
allocated 25 bytes at 0x01e0c1c0 (offset: 128)
allocated 25 bytes at 0x01e0c240 (offset: 128)

same for allocations of 26 to 40 bytes, until:

$ /tmp/test 32 41
allocated 41 bytes at 0x00a72040
allocated 41 bytes at 0x00a720a0 (offset: 96)
allocated 41 bytes at 0x00a72160 (offset: 192)
allocated 41 bytes at 0x00a721c0 (offset: 96)
allocated 41 bytes at 0x00a72280 (offset: 192)

有人可以解释这种行为吗?我完全失去了......

1 个答案:

答案 0 :(得分:0)

posix_memalign仅保证最小对齐。因此,如果您巧合地获得0x00a72000之类的内容,可能会与0x1000字节对齐,但这并不意味着浪费了大量内存来填充它。即使您的第一个示例几乎也显示了这一点 - 它始于0x0198c010并在每个示例之后递增0x30。最终会击中一个清除了许多低位的地址。

请记住,glibc中的malloc不是&#34;愚蠢的&#34;一个只是直接分页/块。如果您想了解有关其内部行为的更多信息,您应该阅读它所基于的分配器。 glibc使用基于ptmallocdlmalloc。我不认为glibc manual本身就其内部设计决策深入探讨。