繁体   English   中英

共享 memory 可以提高 mmap 的性能吗?

[英]Can mmap's performance be improved for shared memory?

我正在为 Wayland 编写一个使用软件渲染和wl_shm进行显示的小程序。 这要求我将屏幕缓冲区的文件描述符传递给 Wayland 服务器,然后在其上调用mmap() ,即屏幕缓冲区必须在进程之间共享。

在这个程序中,启动延迟是关键。 目前,只剩下一个瓶颈:初始绘制到屏幕缓冲区,整个缓冲区都被绘制。 下面的代码显示了这个的简化版本:

#define _GNU_SOURCE
#include <unistd.h>
#include <sys/mman.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main()
{
    /* Fullscreen buffers are around 10-30 MiB for common resolutions. */
    const size_t size = 2880 * 1800 * 4;
    int fd = memfd_create("shm", 0);
    ftruncate(fd, size);
    void *pool = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

    /* Ideally, we could just malloc, but this memory needs to be shared. */
    //void *pool = malloc(size);

    /* In reality this is a cairo_paint() call. */
    memset(pool, 0xCF, size);

    /* Subsequent paints (or memsets) after the first take negligible time. */
}

在我的笔记本电脑上,上面的memset()大约需要 21-28 毫秒。 切换到malloc() 'ed memory 将此时间降至 12 ms,但问题是 memory 需要在进程之间共享。 我的桌面上的行为类似: mmap()为 7 ms, malloc()为 3 ms。

我的问题是:我是否缺少可以提高 Linux 上共享 memory 的性能的东西? 我试过madvise()MADV_WILLNEEDMADV_SEQUENTIAL ,并使用mlock() ,但这些都没有改变。 考虑到大约 10-30 MB 的缓冲区大小,我还考虑过 2MB Huge Pages 是否会有所帮助,但这通常不可用。

编辑:我试过mmap()MAP_ANONYMOUS | MAP_SHARED MAP_ANONYMOUS | MAP_SHARED ,它和以前一样慢。 MAP_ANONYMOUS | MAP_PRIVATE MAP_ANONYMOUS | MAP_PRIVATE导致与malloc()相同的速度,但这违背了目的。

malloc()mmap()之间的性能差异似乎是由于Transparent Hugepages的不同应用。

默认情况下,在 x86_64 上,页面大小为 4KiB,大页面大小为 2MiB。 透明大页面允许不知道大页面的程序仍然使用它们,从而减少页面错误。 这仅在默认情况下对私有匿名 memory 启用 - 因此对于带有 MAP_ANONYMOUS 的malloc()mmap() MAP_ANONYMOUS | MAP_PRIVATE MAP_ANONYMOUS | MAP_PRIVATE集,解释了为什么这些性能是相同的。 对于共享的 memory 映射,这是禁用的,导致更多的页面处理开销(对于我需要的 10-30MiB 缓冲区),并导致速度变慢。

可以通过/sys/kernel/mm/transparent_hugepage/shmem_enabled旋钮为共享 memory 映射启用大页面,如kernel 文档页面中所述。 这默认为never ,但将其设置为always (或advise ,并添加相应的madvise(..., MADV_HUGEPAGE)调用)允许使用MAP_SHARED映射的 memory 使用大页面,并且性能匹配malloc() 'ed memory。

我不确定为什么默认值never用于共享 memory。 虽然不是很令人满意,但目前看来唯一的解决方案是使用madvise(MADV_HUGEPAGE)来提高任何系统的性能,这些系统恰好将shmem_enabled设置为至少advise (或者将来默认启用)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM