我正在编写一个大量使用mmap
的应用程序,包括来自不同进程(不是同时发生,而是串行发送)。性能的一个重要决定因素是TLB如何为这种映射管理用户和内核端。
我理解Linux page cache的用户可见方面。我认为这种理解延伸到用户地区的绩效影响 1 。
我不明白的是这些页面是如何映射到内核空间的,以及它如何与TLB交互(在x86-64上)。您可以在32位x86世界 2 中找到有关它如何工作的大量信息,但我没有找到64位的答案。
所以这两个问题(相互关联,可能一次性回答):
read()
N个页面,那么再次从同一CPU上的另一个进程再次读取这N个页面,可能所有内核端都读取(在内核期间 - >内容的用户空间副本)在TLB中命中?请注意,这(可能)是(1)的直接结果。我的总体目标是深入了解通过mmap
或非mmap
调用(例如read
)一次性访问缓存文件的性能差异。
1 例如,如果您将mmap
文件放入进程的虚拟地址空间,那么您已经有效地要求您的进程页表包含来自返回/请求的虚拟映射的映射地址范围到与页面缓存中该文件的页面相对应的物理范围(即使它们在页面缓存中不存在)。如果指定了MAP_POPULATE
,则在mmap
调用返回之前将实际填充所有页表条目,如果不是,则会在关联页面中填充错误(有时会进行优化,例如{ {3}})。
2 基本上,(对于3:1映射)Linux使用单个1 GB页面直接映射大约1 GB的物理RAM(并将其置于虚拟的前1 GB)内存),这是具有< = 1 GB RAM的机器的故事结束(页面缓存必须在1GB映射中,因此单个1 GB TLB条目涵盖所有内容)。对于超过1GB的RAM,页面缓存优先从“HIGHMEM”分配 - 1GB以上的区域,内核的1GB映射不包含,因此使用了各种fault-around策略。
3 通过映射我的意思是如何为其访问设置页表,又如何虚拟< - >物理制图工作。
答案 0 :(得分:1)
由于与安装的物理ram(内核为128TB)相比存在巨大的虚拟地址空间,因此常见的技巧是永久映射所有ram。这被称为"直接映射"。
原则上,相关的TLB和缓存条目都可能在上下文切换和所有其他代码执行后仍然存在,但很难说这在现实世界中有多大可能。