我非常了解透明大页面的工作原理,并且任何分配,例如由大页面执行的分配,malloc
都可能被大页面满足。
我想知道的是,在分配后是否可以进行任何检查(可能是启发式的)以确定内存是否由大页面支持。
我非常了解透明大页面的工作原理,并且任何分配,例如由大页面执行的分配,malloc
都可能被大页面满足。
我想知道的是,在分配后是否可以进行任何检查(可能是启发式的)以确定内存是否由大页面支持。
您可以通过查找文件中的“pfn”(页框号)来确定任何页面的确切状态,包括它是否由透明(或非透明)大页面支持/proc/kpageflags
。您可以通过读取/proc/$PID/pagemap
进程的文件来获取页面的 pfn,该文件由虚拟地址索引。
不幸的是,pfn
来自pagemap
1的值和整个/proc/kpageflags
文件都只能由 root 用户访问。不过,如果您至少可以在您感兴趣的测试或基准测试场景中以 root 身份运行您的流程,那么这很有效。
我编写了一个名为 page-info 的小型库,它为您进行相关解析。给它一个内存范围,它会在每一页上返回你的信息,包括它是否存在于内存中,是否由大页面支持等。
例如,运行包含的测试过程sudo ./page-info-test THP
会给出以下输出:
PAGE_SIZE = 4096, PID = 18868
size memset FLAG SET UNSET UNAVAIL
0.25 MiB BEFORE THP 0 1 64
0.25 MiB AFTER THP 0 65 0
0.50 MiB BEFORE THP 0 1 128
0.50 MiB AFTER THP 0 129 0
1.00 MiB BEFORE THP 0 1 256
1.00 MiB AFTER THP 0 257 0
2.00 MiB BEFORE THP 0 1 512
2.00 MiB AFTER THP 0 513 0
4.00 MiB BEFORE THP 0 1 1024
4.00 MiB AFTER THP 512 513 0
8.00 MiB BEFORE THP 0 1 2048
8.00 MiB AFTER THP 1536 513 0
16.00 MiB BEFORE THP 0 1 4096
16.00 MiB AFTER THP 3584 513 0
32.00 MiB BEFORE THP 0 1 8192
32.00 MiB AFTER THP 7680 513 0
64.00 MiB BEFORE THP 0 1 16384
64.00 MiB AFTER THP 15872 513 0
128.00 MiB BEFORE THP 0 1 32768
128.00 MiB AFTER THP 32256 513 0
256.00 MiB BEFORE THP 0 1 65536
256.00 MiB AFTER THP 65024 513 0
512.00 MiB BEFORE THP 0 1 131072
512.00 MiB AFTER THP 124416 6657 0
1024.00 MiB BEFORE THP 0 1 262144
1024.00 MiB AFTER THP 0 262145 0
DONE
该UNAVAIL
列表示没有可用的映射信息 - 通常是因为该页面从未被访问过,因此根本没有任何页面支持。您可以看到,对于这些“大”分配,在分配之后只映射了一个页面,因为我们没有触及内存。
在调用整个分配之后,这些AFTER
行是相同的信息,这会导致所有页面都被物理分配。memset()
在这里,我们可以看到透明大页不支持任何分配,直到我们达到 4 MiB 的分配,此时每个分配的大部分都由 THP 支持,除了 513 个页面(结果位于分配区域的边缘)。在 512 MiB 时,系统开始用尽可用的大页面,但仍满足大部分分配,但在 1024 MiB 时,整个分配对小页面感到满意。
这个库不是生产就绪的,所以不要将它用于任何关键的事情(例如,一些失败只是调用exit()
)。欢迎投稿。
1大约从内核 4.0 开始,在此之前,非 root 用户进程可以访问 pfn。从 4.0 到 4.1 左右,整个pagemap
进程都禁止非 root 进程使用,但此后文件再次可用,但 pfn 被屏蔽(它始终显示为零)。
传统的大页面和透明大页面 (THP) 之间存在差异。在 THP 的情况下,应用程序可以在没有任何开发人员支持(mmap、shmget 等)或系统管理员干预的情况下使用大页面。
在代码中,恐怕可能没有直接的方法来检查这一点。但是,如果您知道 sizeof() 分配的数据结构或缓冲区,则值得使用以下命令 grepping 并检查系统上的 THP 使用情况。在运行您的应用程序时,这种使用应该会增加:
# grep AnonHugePages /proc/meminfo
AnonHugePages: 2648064 kB