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