内存/提交充电在 Windows 10 中如何工作?

内存/提交充电在 Windows 10 中如何工作?

这个问题是由以下经常观察到的现象引发的,我希望找到其解释:

  1. 当前提交通常高于物理使用量 + 页面文件大小。这是怎么回事?这难道不可能吗?[这似乎可能是因为压缩。这把问题转化为:为什么提交限制不会上升或类似情况?也就是说,如果压缩对内存使用量没有帮助,那压缩有什么意义呢?]
  2. 有时会达到极端水平,当前提交是物理内存使用量的两倍以上!
  3. 当提交电量已满并且 Windows 开始要求我关闭某些东西时,大多数时候物理内存的使用率都在 60% 左右。这似乎非常低效。

据 Process Explorer 报告,这是在 Windows 10 上发生的。

我最想回答的问题是:我是否可以放弃人为地将页面文件扩大到空间不足的固态硬盘无法处理的级别,以便真正有效地利用物理内存?(或者即使它没有那么满。也就是说,我想避免诸如“对页面文件执行 X/Y/Z”之类的建议。)

答案1

一旦你理解了提交费用仅代表潜在的- 但“保证在你需要时可用” - 使用虚拟内存,而“私有工作集” - 本质上是“已提交”内存使用的 RAM - 是实际的使用,页面文件空间也是如此。(但这并不是 RAM 的全部使用,因为还有其他东西使用 RAM)。

假设我们讨论的是 32 位系统,因此每个进程可用的最大虚拟地址空间通常为 2 GiB。(在任何对于 64 位系统,除了地址和大小可以更大 - 大得多。)

现在假设进程中运行的程序使用 VirtualAlloc(Win32 API)“提交” 2 MiB 的虚拟内存。正如您所预料的,这将显示为额外的 2 MiB 提交费用,并且进程中可供将来分配的虚拟地址空间字节数减少了 2 MiB。

但它实际上还不会使用任何物理内存(RAM)!

VirtualAlloc 调用将向调用者返回已分配区域的起始地址;该区域将位于 0x10000 到 0x7FFEFFFF 范围内,即大约 2 GiB。(每个进程中 vas 的第一个和最后一个 64KiB(或十六进制的 0x10000)从未分配。)

但同样,2MiB 并没有实际的物理用途贮存还没有!不在 RAM 中,甚至不在页面文件中。(有一个称为“虚拟地址描述符”的微小结构,它描述了私有提交区域的起始 va 和长度。)

就是这样!提交费用增加了,但物理内存使用量却没有增加。

使用 sysinternals 工具可以很容易地演示这一点testlimit

稍后,假设程序在该区域(无论在哪里)存储了某些内容(即内存写入操作)。该区域下方还没有任何物理内存,因此此类访问将引发页面错误对此,操作系统的内存管理器,特别是页面错误处理程序例程(简称“分页器”……称为 MmAccessFault),将:

  1. 分配一个先前“可用”的物理页面
  2. 设置所访问的虚拟页的页表项,以将虚拟页号与新分配的物理页号关联起来
  3. 将物理页面添加到进程私有工作集
  4. 并消除页面错误,导致重试引发错误的指令。

现在,您已将一个页面 (4 KiB) “故障” 到进程中。物理内存使用量将相应增加,而“可用” RAM 将减少。提交费用不变。

一段时间后,如果该页面有一段时间没有被引用,而且对 RAM 的需求很高,则可能会发生以下情况:

  1. 操作系统从进程工作集中删除该页面。
  2. 由于自从被带入工作集以来就被写入,因此它被放入修改页面列表(否则它将进入备用页面列表)。页表条目仍然反映 RAM 页面的物理页码,但现在其“有效”位已清除,因此下次引用它时将发生页面错误
  3. 当修改后的页面列表达到一个小的阈值时,修改页面写入器“系统”进程中的线程被唤醒并将修改后的页面的内容保存到页面文件(假设您有一个),并且......
  4. 将这些页面从已修改列表中移除,并将它们放入待机列表中。它们现在被视为“可用”RAM 的一部分;但目前它们仍保留着它们在各自进程中的原始内容。同样,提交费用不会改变,但 RAM 使用率和进程私有工作集会下降。
  5. 待机列表中的页面现在可以重新利用,也就是说用于其他用途 - 例如解决系统上任何进程的页面错误,或由 SuperFetch 使用。但是...
  6. 如果某个进程在已修改或待机列表中丢失了页面,并在物理页面重新利用之前(即仍保留其原始内容)尝试再次访问该页面,则无需从磁盘读取即可解决页面错误。只需将该页面放回进程工作集中,并使页表条目变为“有效”即可。这是“软”或“廉价”页面错误的一个例子。我们说待机和已修改列表形成了一个系统范围的页面缓存,这些页面可能很快会再次需要。

如果您没有页面文件,则步骤 3 至 5 将更改为:

  1. 这些页面位于已修改列表中,因为没有地方可以写入其内容。

  2. 这些页面位于已修改列表中,因为没有地方可以写入其内容。

  3. 这些页面位于已修改列表中,因为没有地方可以写入其内容。

第 6 步保持不变,因为修改列表上的页面可以作为“软”页面错误返回到丢失它们的进程。但如果没有发生这种情况,这些页面将停留在修改列表中,直到进程释放相应的虚拟内存(可能是因为进程结束)。

除了私有已提交内存之外,虚拟地址空间和 RAM 还有其他用途。映射虚拟地址空间,其后备存储是某个指定文件而不是页面文件。已调入的映射 vas 页面反映在 RAM 使用量中,但映射内存不计入提交费用,因为映射文件提供了后备存储:映射区域的任何不在 RAM 中的部分都只是保存在映射文件中。另一个区别是大多数文件映射可以在进程之间共享;一个进程内存中已有的共享页面可以添加到另一个进程,而无需再次进入磁盘(另一个软页面错误)。

还有不可分页vas,它没有后备存储,因为它始终驻留在 RAM 中。这既增加了报告的 RAM 使用量,也增加了“提交费用”。

这似乎可能是因为压缩。问题就变成了:为什么不提交限制然后增加或诸如此类的?也就是说,如果压缩对内存使用没有帮助,那它有什么意义呢?

不。这与压缩无关。Windows 中的内存压缩是作为中间步骤进行的,针对原本会写入页面文件的页面。实际上,它允许修改页面列表使用更少的 RAM 来容纳更多的东西,虽然会花费一些 CPU 时间,但速度却比页面文件 I/O 快得多(即使是 SSD)。由于提交限制是从全部的RAM + 页面文件大小,而不是 RAM 使用量 + 页面文件使用量,这不会影响提交限制。提交限制不会因 RAM 使用量或用途而改变。

当提交电量已满并且 Windows 开始要求我关闭某些东西时,大多数时候物理内存的使用率都在 60% 左右。这似乎非常低效。

这并不是说 Windows 效率低下。而是你运行的应用程序效率低下。它们占用的资源比实际使用的多得多。

整个“提交电荷”和“提交限制”机制的原因是:当我调用 VirtualAlloc 时,我应该检查返回值以查看它是否为非零。如果它为零,则意味着我的分配尝试失败,可能是因为它会导致提交电荷超过提交限制。我应该做一些合理的事,比如尝试提交更少的电荷,或者干净地退出程序。

如果 VirtualAlloc 返回非零值,即一个地址,这告诉我系统已经做出了保证——如果你愿意的话,这是一个承诺——无论我要求多少个字节,从该地址开始,如果我选择访问它们,它们都是可用的;有地方可以放置它们 - RAM 或页面文件。也就是说,没有理由认为访问该区域内的任何内容时会出现任何类型的失败。这很好,因为期望我在每次访问分配的区域时都检查“它是否有效?”是不合理的。

“现金贷款银行”类比

这有点像银行提供信贷,但严格以现金为基础。(当然,这不是真正的银行的运作方式。)

假设银行一开始手头有 100 万美元现金。人们去银行申请不同数额的信用额度。假设银行批准我获得 100,000 美元的信用额度(我创建了一个私人承诺区域);这并不意味着任何现金实际上都离开了金库。如果我后来实际贷款 20,000 美元(我访问该区域的子集),这确实会从银行中扣除现金。

但无论我是否贷款,我最多获批 10 万美元贷款,这意味着银行随后只能为所有客户批准另外 90 万美元的信用额度。银行不会批准超过其现金储备的信用额度(即不会过度承诺因为他们可能已经获得了贷款批准,但银行可能不得不拒绝他们,因为他们后来又打算借钱他们的贷款。这将是非常糟糕的,因为银行已经坚定的允许这些贷款,银行的声誉就会一落千丈。

是的,从银行对现金的使用角度看,这是“低效的”。客户获批的信用额度和他们实际借贷的金额之间的差距越大,效率就越低。但这种低效并不是银行的错;这是客户的“错”,因为他们要求如此高的信用额度,但只借了小额贷款。

该银行的业务模式是,当借款人前来申请贷款时,银行根本无法拒绝他们——否则对客户来说将是“致命的”。这就是为什么银行会仔细追踪贷款资金中有多少已被“承诺”。

我认为扩展页面文件或添加另一个页面文件就像银行出去获取更多现金并将其添加到贷款基金中一样。

如果您想用这个比喻来模拟映射和不可分页内存……不可分页就像一笔小额贷款,您在开立账户时需要取出并保留。(定义每个新流程的不可分页结构。)映射内存就像带上自己的现金(正在映射的文件)并将其存入银行,然后一次只取出部分(将其分页)。为什么不一次全部分页呢?我不知道,也许您的钱包里没有足够的空间放那么多现金。:) 这不会影响其他人借钱的能力,因为您存入的现金在您自己的账户中,而不是一般贷款基金中。这个比喻从那里开始不成立,尤其是当我们开始考虑共享内存时,所以不要把它推得太远。

回到 Windows 操作系统:事实上,您有大量 RAM“可用”,这与提交费用和提交限制无关。如果您接近提交限制,则意味着操作系统已经提交 - 即 承诺提供当要求时 - 那么多存储空间。不必全部使用即可强制执行限制。

我是否可以放弃人为地将页面文件扩大到空间不足的 SSD 无法处理的级别,以便真正有效地利用物理内存?(或者即使它没有那么满。也就是说,我想避免诸如“对页面文件执行 X/Y/Z”之类的建议。)

嗯,很抱歉,但是如果您遇到了提交限制,那么您可以做三件事:

  1. 增加你的 RAM。
  2. 增加页面文件的大小。
  3. 一次运行较少的东西。

关于选项 2:您可以将第二个页面文件放在硬盘上。如果应用程序实际上没有使用所有已提交的内存(显然它们没有,因为您看到如此多的可用 RAM),您实际上不会经常访问该页面文件,因此将其放在硬盘上不会影响性能。如果硬盘的缓慢仍然会困扰您,另一个选择是购买一个小巧便宜的第二个 SSD,并将第二个页面文件放在上面。唯一的“障碍”是笔记本电脑无法添加第二个“不可移动”驱动器。(Windows 不允许您将页面文件放在可移动驱动器上,例如任何通过 USB 连接的驱动器。)

这是我写的另一个答案从不同的方向解释事情。

附言:您问的是 Windows 10,但我应该告诉您,NT 系列的每个版本都以相同的方式工作,最早是 NT 3.1,预发布版本也是如此。可能发生变化的是 Windows 的页面文件大小默认设置,从 1.5 倍或 1 倍 RAM 大小变为小得多。我相信这是一个错误。

相关内容