【问题标题】:glibc posix_memalign allocation overheadglibc posix_memalign 分配开销
【发布时间】:2016-02-05 21:16:45
【问题描述】:

我试图了解与 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)

谁能解释这种行为?我完全不知所措...

【问题讨论】:

    标签: glibc


    【解决方案1】:

    posix_memalign 只保证最小对齐。因此,如果您碰巧得到类似0x00a72000 的东西,它可能与0x1000 字节对齐,但这并不意味着浪费了大量内存来填充它。甚至您的第一个示例 几乎 也显示了这一点 - 它从 0x0198c010 开始,并在每个之后递增 0x30。最终,它会到达一个清除了许多低位的地址。

    请记住,glibc 中的 malloc 并不是一个“愚蠢”的,它只是线性地分发页面/块。如果你想了解更多关于它的内部行为,你应该阅读它所基于的分配器。 glibc 使用基于dlmallocptmalloc。我认为glibc manual 本身并没有深入了解其内部设计决策。

    【讨论】:

    • 但是如何解释后续分配之间的偏移量变化这一事实(即第二个示例的结果)?
    • 我没有看到任何不好或不寻常的地方。 ptmalloc 有多个用于分配内存的 arena。
    猜你喜欢
    • 2014-02-07
    • 2010-09-07
    • 2015-05-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-23
    • 2014-11-12
    相关资源
    最近更新 更多