4.3.2. 影响 TLB 效能
有几个影响 TLB 效能的因素。第一个是分页的大小。显然地,分页越大、会被塞进去的指令或资料物件也越多。所以一个比较大的cache大小减少了所需地址转译的整体数量,代表 TLB cache中需要更少的项目。大部分架构现今允许使用多种不同的分页大小;有些大小能够并存地使用。举例来说,x86/x86-64 处理器拥有寻常的 4kB 分页大小,但它们也分别能够使用 4MB 与 2MB 的分页。IA-64 与 PowerPC 允许像是 64kB 的大小作为基础分页大小。
不过,大分页尺寸的使用也随之带来了一些问题。为了大分页而使用的memory区域在实体memory中必须是连续的。若是实体memory管理的单位大小被提高到虚拟memory分页的大小,浪费的memory总量就会增加。各种memory操作(像是载入可执行程序)需要对齐到分页边界。这表示,平均而言,在每次映射的实体memory中,每次映射浪费了一半的分页大小。这种浪费能够轻易地累加;这因此对实体memory分配的合理单位大小加了个上限。
将单位大小提升到 2MB,以容纳 x86-64 上的大分页无疑并不实际。这个大小太大了。但这又意味著每个大分页必须由多个较小的分页所构成。而且这些小分页在实体memory中必须是连续的。以 4kB 的单位分页大小分配 2MB 的连续实体memory具有挑战性。这需要寻找一个有著 512 个连续分页的空閒区域。在系统执行一段时间、并且实体memory变得片段之后,这可能极端困难(或者不可能)。
因此在 Linux 上,有必要在系统启动的时候使用特殊的 hugetlbfs 档案系统来分配这些大分页。一个固定数量的实体分页会被保留来专门作为大虚拟分页来使用。这绑住了可能不会一直用到的资源。这也是个有限的池(pool);增加它通常代表著重新启动系统。尽管如此,在效能贵重、资源充足、且麻烦的设置不是个大阻碍的情况下,庞大的分页便为大势所趋。资料库服务器就是个例子。
$ eu-readelf -l /bin/ls
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
...
LOAD 0x000000 0x0000000000400000 0x0000000000400000 0x0132ac 0x0132ac R E 0x200000
LOAD 0x0132b0 0x00000000006132b0 0x00000000006132b0 0x001a71 0x001a71 RW 0x200000
...
提高最小的虚拟分页大小(对比于可选的大分页)也有它的问题。memory映射操作(例如,载入应用程序)必须遵循这些分页大小。不可能有更小的映射。一个可执行程序不同部分的位置 –– 对大多架构而言 –– 有个固定的关系。若是分页大小增加到超过在可执行程序或者 DSO 创建时所考虑的大小时,就无法执行载入操作。将这个限制记在心上是很重要的。图 4.3 显示了能够如何决定一个 ELF 二进位资料(binary)的对齐需求的。它被编码在 ELF 的程序标头(header)。在这个例子中,一个 x86-64 的二进位资料,值为 ,与处理器所支援的最大分页大小相符。
使用较大的分页大小有个次要的影响:分页表树的层级数量会被减低。由于对应到分页偏移量的虚拟地址部分增加了,就没有剩下那么多需要透过分页目录处理的位元了。这表示,在一次 TLB 错失的情况下,必须完成的工作总量减少了。
除了使用大分页尺寸外,也可能借由将同时用到的资料搬移到较少的分页上,以减少所需的 TLB 项目数量。这类似于我们先前讨论的针对cache使用的一些最佳化。 Only now the alignment required is large. 考虑到 TLB 项目的数量非常少,这会是个重要的最佳化。