使用匿名 mmap() 检查实际分配的页面数
Checking number of actually allocated pages using anonymous mmap()
我正在使用带有 MAP_ANONYMOUS
标志的 mmap()
分配一些内存。由于问题的特点,我经常需要将一些数据写入大内存块的一页(例如位于中间),而另一部分保持不变。因此,我不会将这一相当大的未使用内存分配给物理分配。
在我看来,这样的 mmap()
调用只是给我一个指向一些 0 填充的虚拟页面的指针,但是由于写时复制和请求分页机制,没有一页(除了第一个可能) 在第一次尝试写入它的内存之前实际上并没有分配到 RAM 中。
问题是:当我尝试分配大于我的物理内存大小。因此,似乎实际上分配了更多的页面,即使没有对它们的写访问权限。
我需要你们帮忙解决两个问题,首先:
我对匿名内存分配的看法是否正确,(如果不正确)有哪些不准确之处?
第二个:
完成匿名 mmap()
后,如何测量实际分配的页面数?我试过使用 mincore()
,结果显示几乎所有页面都在内存中 "resident"(即物理分配?)。所以,似乎 mincore()
结果是错误的,或者我完全被卡住了:(
更新
@Art 提到的内存过度使用似乎确实会影响这一点。但是当我试图禁用它时(将 /proc/sys/vm/overcommit_memory
设置为 1
模式或使用 mmap()
和 MAP_NORESERVE
标志,我的机器严重冻结,硬重置是唯一有帮助的东西。
"It's complicated."(警告:我从 Linux 那里获得了更多的 VM 系统经验,但多年来我从 Linux 那里获得了一些细节)
大体上你的假设是正确的。除了记录 "there is an allocation of X pages of object Y at V",许多操作系统实际上并没有在 mmap
上做太多事情。访问这些页面会导致页面错误,从而导致实际分配。 Linux 的某些(或全部?)版本将 pre-zeroed read-only 页面映射到此类分配(不确定它是否已更改或是否仍在完成),其余的处理方式如下 copy-on-write(对我来说,这感觉是个坏主意,因为它应该生成更多的 TLB 刷新以进行可疑的读取清零内存的优化,这种情况应该很少发生,但我猜 Linux 人们已经对它进行了基准测试并发现它很好) .
有一些注意事项。仅仅因为您不使用 RAM 并不意味着您将被允许过量使用这么多内存。某些 Linux 发行版开始时默认设置为不允许过度使用或不允许超过 X% 的过度使用。 Centos/RedHat 就是其中之一(这可能是十年前的事了,我不知道今天的状态)。这意味着即使您只使用了 5% 的实际物理内存,如果您创建了 100+X% RAM 的匿名映射,mmap 也会失败。有一个 sysctl,查一下。它类似于 /proc/sys/vm/overcommit_memory
或 overcommit_ratio
或两者兼而有之,或者可能更多。
那你就要注意资源的限制了。检查 ulimit
是否允许创建这么大的映射 (ulimit -v),问题可能就这么简单。另外(我不确定 Linux 在这里是如何做到的,但您可以创建简单的测试程序来尝试),数据大小的资源限制 (ulimit -d) 可以被视为您可以使用的潜在页面,而不是您当前使用的实际页面(换句话说,资源限制没有过度使用)。
然后让我们回到仅在您使用的页面中出现故障。已经对检测访问模式和预测未来故障进行了研究(因此 mmap:ed 文件可以做到 read-ahead),但我不知道它在 Linux 中的状态。感觉将其应用于匿名映射会很愚蠢,但你永远不知道,也许有人在耍小聪明。为了确保,请在您获得的 mmap:ed 块上使用 madvise(..., MADV_RANDOM)
。
终于mincore
。我在 Linux 上的经验是它是垃圾,上次我尝试它对匿名映射不起作用(或者它是私有的?)。在您的情况下,它可能就像报告匿名映射的 read-only copy-on-write 归零页面被认为是 "in core".
一样简单
我正在使用带有 MAP_ANONYMOUS
标志的 mmap()
分配一些内存。由于问题的特点,我经常需要将一些数据写入大内存块的一页(例如位于中间),而另一部分保持不变。因此,我不会将这一相当大的未使用内存分配给物理分配。
在我看来,这样的 mmap()
调用只是给我一个指向一些 0 填充的虚拟页面的指针,但是由于写时复制和请求分页机制,没有一页(除了第一个可能) 在第一次尝试写入它的内存之前实际上并没有分配到 RAM 中。
问题是:当我尝试分配大于我的物理内存大小。因此,似乎实际上分配了更多的页面,即使没有对它们的写访问权限。
我需要你们帮忙解决两个问题,首先: 我对匿名内存分配的看法是否正确,(如果不正确)有哪些不准确之处?
第二个:
完成匿名 mmap()
后,如何测量实际分配的页面数?我试过使用 mincore()
,结果显示几乎所有页面都在内存中 "resident"(即物理分配?)。所以,似乎 mincore()
结果是错误的,或者我完全被卡住了:(
更新
@Art 提到的内存过度使用似乎确实会影响这一点。但是当我试图禁用它时(将 /proc/sys/vm/overcommit_memory
设置为 1
模式或使用 mmap()
和 MAP_NORESERVE
标志,我的机器严重冻结,硬重置是唯一有帮助的东西。
"It's complicated."(警告:我从 Linux 那里获得了更多的 VM 系统经验,但多年来我从 Linux 那里获得了一些细节)
大体上你的假设是正确的。除了记录 "there is an allocation of X pages of object Y at V",许多操作系统实际上并没有在 mmap
上做太多事情。访问这些页面会导致页面错误,从而导致实际分配。 Linux 的某些(或全部?)版本将 pre-zeroed read-only 页面映射到此类分配(不确定它是否已更改或是否仍在完成),其余的处理方式如下 copy-on-write(对我来说,这感觉是个坏主意,因为它应该生成更多的 TLB 刷新以进行可疑的读取清零内存的优化,这种情况应该很少发生,但我猜 Linux 人们已经对它进行了基准测试并发现它很好) .
有一些注意事项。仅仅因为您不使用 RAM 并不意味着您将被允许过量使用这么多内存。某些 Linux 发行版开始时默认设置为不允许过度使用或不允许超过 X% 的过度使用。 Centos/RedHat 就是其中之一(这可能是十年前的事了,我不知道今天的状态)。这意味着即使您只使用了 5% 的实际物理内存,如果您创建了 100+X% RAM 的匿名映射,mmap 也会失败。有一个 sysctl,查一下。它类似于 /proc/sys/vm/overcommit_memory
或 overcommit_ratio
或两者兼而有之,或者可能更多。
那你就要注意资源的限制了。检查 ulimit
是否允许创建这么大的映射 (ulimit -v),问题可能就这么简单。另外(我不确定 Linux 在这里是如何做到的,但您可以创建简单的测试程序来尝试),数据大小的资源限制 (ulimit -d) 可以被视为您可以使用的潜在页面,而不是您当前使用的实际页面(换句话说,资源限制没有过度使用)。
然后让我们回到仅在您使用的页面中出现故障。已经对检测访问模式和预测未来故障进行了研究(因此 mmap:ed 文件可以做到 read-ahead),但我不知道它在 Linux 中的状态。感觉将其应用于匿名映射会很愚蠢,但你永远不知道,也许有人在耍小聪明。为了确保,请在您获得的 mmap:ed 块上使用 madvise(..., MADV_RANDOM)
。
终于mincore
。我在 Linux 上的经验是它是垃圾,上次我尝试它对匿名映射不起作用(或者它是私有的?)。在您的情况下,它可能就像报告匿名映射的 read-only copy-on-write 归零页面被认为是 "in core".