我正在编写一个小程序,用于在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()
分配的内存可以将这个时间降低到12毫秒,但问题是这些内存需要在进程之间共享。在我的台式机上,情况类似:使用mmap()
花费7毫秒,使用malloc()
花费3毫秒。我的问题是:我是否遗漏了什么可以提高Linux上共享内存性能的东西?我尝试过使用madvise()
和MADV_WILLNEED
以及MADV_SEQUENTIAL
,以及使用mlock()
,但这些都没有改善性能。我也考虑过是否使用2MB的Huge Pages会有帮助,因为缓冲区大小大约在10-30 MB左右,但通常不可用。
编辑:我尝试过使用mmap()
和MAP_ANONYMOUS | MAP_SHARED
,速度与之前一样慢。而使用MAP_ANONYMOUS | MAP_PRIVATE
则与使用malloc()
速度相同,但这违背了初衷。
memset()
大约需要 2 毫秒。我会编辑代码并进行澄清。 - Pjj56time
下运行它也会计算较小的页面错误的数量,这很可能就是时间消耗的地方。如果您使用不同数量的页面time
运行几次,您可以轻松验证这一点。 - Useless