1

JVM 剖析花园:2 - 透明大页

 7 months ago
source link: https://www.diguage.com/post/jvm-anatomy-quarks-02-transparent-huge-pages/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

JVM 剖析花园:2 - 透明大页

2024-01-13
JVM 剖析花园:2 - 透明大页

什么是大页(Large Page)?什么是透明大页(Transparent Huge Page)?它对我有什么帮助?

虚拟内存现在已被视为理所当然。现在只有少数人还记得,更不用说做一些“真实模式”编程了,在这种情况下,你会接触到实际的物理内存。相反,每个进程都有自己的虚拟内存空间,该空间被映射到实际内存上。例如,两个进程在相同的虚拟地址 0x42424242 上拥有不同的数据,而这些数据将由不同的物理内存支持。现在,当程序访问该地址时,应将虚拟地址转换为物理地址。

虚拟内存地址与物理内存地址之间的关系
Figure 1. 虚拟内存地址与物理内存地址之间的关系

这通常由操作系统维护 “页表”,硬件通过“页表遍历”来实现地址转换。如果在页面粒度上维护翻译,整个过程就会变得简单。但这样做的成本并不低,而且每次内存访问都需要这样做!因此,还需要对最新的翻译进行小型缓存,即 转译后备缓冲区(Translation Lookaside Buffer (TLB))。TLB 通常很小,只有不到 100 个条目,因为它的速度至少要与 L1 缓存相当,甚至更快。对于许多工作负载来说,TLB 未命中和相关的页表遍历需要大量时间。

既然我们无法将 TLB 做得更大,那么我们可以做其他事情:制作更大的页面!大多数硬件有 4K 基本页和 2M/4M/1G “大页”。用更大的页来覆盖相同的区域,还能使页表本身更小,从而降低页表遍历的成本。

在 Linux 世界中,至少有两种不同的方法可以在应用程序中实现这一点:

  • hugetlbfs。切出系统内存的一部分,将其作为虚拟文件系统公开,让应用程序通过 mmap(2) 从其中获取。这是一个特殊的接口,需要操作系统配置和应用程序更改才能使用。这也是一种“要么全有,要么全无”的交易:分配给 hugetlbfs(持久部分)的空间不能被普通进程使用。

  • 透明大页(Transparent Huge Pages (THP))。让应用程序像往常一样分配内存,但尽量以透明方式为应用程序提供大容量页面支持的存储空间。理想情况下,不需要更改应用程序,但我们会看到应用程序如何从了解 THP 的可用性中获益。但在实际应用中,会产生内存开销(因为会为小文件分配整个大页面)或时间开销(因为 THP 有时需要对内存进行碎片整理以分配页面)。好在有一个中间方案:通过 madvise(2) 可以让应用程序告诉 Linux 在哪里使用 THP。

不明白为什么术语中会交替使用 "large "和 "huge"。总之,OpenJDK 支持这两种模式:

-XX:+UseHugeTLBFS 将 Java 堆映射到 hugetlbfs 中,后者应单独准备。

-XX:+UseTransparentHugePages 参数已经在“疯狂”地提示 Java 堆应使用 THP。这是一个很方便的选项,因为我们知道 Java 堆很大,而且大部分是连续的,可能从大页面中获益最多。

-XX:+UseLargePages 是一个通用快捷方式,可以启用任何可用的选项。在 Linux 上,它启用的是 hugetlbfs,而不是 THP。我猜这是出于历史原因,因为 hugetlbfs 最先出现。

某些应用程序在启用大页面后确实会 受到影响。(有趣的是,有时看到人们为了避免 GC 而手动进行内存管理,结果却因为 THP 磁盘碎片而导致延迟激增!)。直觉告诉我,THP 会让大部分短暂的应用程序倒退,在这些应用程序中,碎片整理成本与短应用程序时间相比是显而易见的。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK