Windows如何如此快地将完整的RAM转储到休眠文件中?


64

我正在浏览一篇介绍Microsoft Windows休眠过程的文章。我从中得到的要点是

  1. Windows将整个RAM转储到hiberfil.sys文件中(可能经过处理后)。
  2. 在启动过程中,将读取休眠文件,并将内容加载到RAM中。

我的问题是,当我通常复制一个大小为1 GB的文件时,大约需要2分钟才能完成。

但是,在Windows编写休眠文件时(在休眠过程中),整个过程可能需要10到15秒。 为什么写入速度会有如此差异?

我的RAM大小是4 GB。(我不是在谈论快速启动技术。)

基准测试:

  1. 将1 GB的文件从磁盘1复制到磁盘2(外部):2.3分钟。
  2. 休眠系统:15秒。

3
我不知道答案,但是我敢打赌,如果您检查了Windows Internals一书“第13章:启动和关闭”,它会告诉您(如果我自己有这本书,我会检查)。
Scott Chamberlain 2015年

2
这是一个很好的问题。1998年首次实施休眠模式时,并没有那么快。
加布2015年

22
@coder:NT系统确保hyberfil.sys分配了全部空间,并且整个文件没有碎片。在这种情况下,操作过程中硬盘上不会出现磁头跳动。因此,您将获得有效速度,例如150Mo / s。您可以重新检查我说的内容fsutil
user2284570 2015年

3
外部磁盘通常也比内部磁盘慢。
哈里·约翰斯顿

2
@EricLippert-它肯定不会存储所有RAM,但这仍然无法解释。我通常需要存储几GB的活动RAM(VS2013或Eclipse +很少的东西要花很多内存),并且它们的存储速度对我来说似乎甚至比非SSD的理论写入速度还高。驾驶。
Davor

Answers:


45

这可能是三个答案。

Windows中可能发生的一件事是Windows中新的Hybrid Shutdown(混合关闭),它可以有效关闭应用程序,注销您的帐户,然后继续休眠操作系统的核心。已经保存了该数据将意味着它不需要潜在地“重新休眠”。

第二件事是休眠状态无需保存已调出到交换文件或未使用的内存页面(这是积极填充交换文件并将数据保留在内存中的原因之一) 。

第三是休眠文件数据也被压缩。结合我的第二点,如果要导出的数据中只有一小部分包含高度可压缩的数据(可执行文件通常被很好地压缩),那么进入休眠文件的数据量可能比工作集小得多。数据的。请注意,如注释中所述,文件缓存和其他不必要的缓冲区数据很容易被丢弃,而没有不良影响,从而减少了要在休眠文件中转储的数据量。

此外,当前的硬盘驱动器非常快。使用持续写入速度约为100 MB / s的磁盘,您将能够在一分钟之内写出(未压缩的)4 GB RAM。在挂起所有用户进程之后且挂起CPU之前,休眠是最后的事情,因此OS通常具有磁盘的完整写入速度。这是您的简单基准测试所没有的一件事,从磁盘复制到磁盘可能比仅将RAM写入磁盘要慢。

结合这些因素,将要写入休眠文件的数据量可能非常小,可能约为1 GB,并且可能会在10秒内写入一个大的连续块中。


37
或者,更明确地说:您的RAM可能未满。休眠时刷新缓冲区,并丢弃高速缓存。只有应用程序实际使用的内存才需要写入磁盘。混合关闭通过注销用户来减少正在使用的内存量。
丹尼尔·B

2
不脏页是“分页到交换文件”的更一般的声明,其中将包括可执行文件。(由于可执行文件在磁盘上有些碎片,因此可能会降低唤醒速度。)此外,大概可以删除干净的文件缓冲区,即使它们不属于内存映射文件也是如此。
Paul A. Clayton

3
我在该答案中链接的文档中@@ user2284570 “ Windows通过将内存内容复制到磁盘来支持休眠。系统在将内存内容保留在磁盘上之前先对其进行压缩,这将所需的磁盘空间减少到小于物理内存总量“
Mokubai

4
@ user2284570:这是因为最坏的情况是1:1压缩。Windows必须确保在hyberfil.sys中有足够的(保留)空间用于任何可能的内存配置-即使对于特定的休眠状态它仅需要RAM大小的十分之一。此外,RAM使用中相当一部分是将文件加载到内存(可执行文件,资源...),但仍从HDD映射,因此您确实可以节省大量编写工作。让一个程序在RAM中生成4 GiB的加密随机数据,并且休眠会花费更长的时间-即便如此,其中一些可能仍在交换中。
罗安2015年

3
@ user2284570:该文件太大,以确保磁盘上有足够的空间来存储所有内存。实际上,并不是所有的空间都用于休眠。有时,文件将(例如)压缩后的内存内容占7%,而垃圾内容占93%。
psmears'3

31

首先,需要节省的RAM数量非常少。实际上,仅需要清除一组映射的脏页(“惰性写回”),并且还需要写入已写入并重定位了可执行代码的所有私有页。

  • 可执行文件的.text段始终由文件映射支持。至少对于某些 DLL 也是如此(但并非全部,这取决于是否需要重定位)。
  • 类似地,由文件映射支持的内存也可以被丢弃(假定它不是CoW或RW 脏了)。
  • 仍然需要进行延迟写回,但是除此之外,可以丢弃缓存。
  • 已分配但未写入的内存(通常是应用程序数据的绝大部分!)由零页支持,可以丢弃。
  • 那是对内存页面的更大一部分“待机”状态(在Windows上实际每进程驻留工作集是惊人地小,区区16MB)将已在某些时候被复制到页面文件在后台可以被丢弃。
  • 某些设备(例如图形卡)映射的内存区域可能(不需要)保存。用户有时会惊讶地发现他们将8GiB或16GiB插入计算机,而1GiB或2GiB只是“消失”,没有明显的原因。主要的图形API要求应用程序能够“在某些情况下”使缓冲区内容变为无效(而不能确切说明其含义)。因此,可以预料图形驱动器固定的内存也将被丢弃。毕竟,屏幕还是会变黑。

其次,与复制文件相反,从驱动器的角度来看,转储需要保存磁盘的RAM页面集是一次连续的连续写入。Win32 API甚至为此操作公开了一个用户级功能。硬件直接支持聚集写入,并且其工作速度与磁盘在物理上能够接收数据的速度一样快(控制器将直接通过DMA提取数据)。
这项工作需要满足许多先决条件(例如对齐,块大小,固定),并且不能很好地与缓存一起使用,也没有“延迟写回”之类的东西(在正常操作下这是非常理想的优化) )。
这就是为什么不是每个写的原因一直这样工作。但是,当系统保存休眠文件时,将自动满足所有前提条件(所有数据都是页面对齐的,页面大小且固定的),并且缓存已变得无关紧要,因为即将关闭计算机。

第三,对于旋转磁盘和固态磁盘而言,执行一次连续写入都是非常有利的

交换文件和休眠文件通常是在磁盘上创建和保留的最早的文件。它们通常有一个,最多两个碎片。因此,除非扇区损坏并且磁盘必须重新分配物理扇区,否则逻辑顺序写入将转换为旋转磁盘上的物理顺序写入。

当写入大量连续的连续数据时,磁盘上无需进行读-修改-写操作。在可以写入非常小的单个扇区的旋转硬盘上,此问题不太明显(假设您不写入单个字节,这通常可以防止缓存,设备不需要获取原始内容并写回修改后的版本。) 。
但是,这在SSD上非常明显,因为每次写入都意味着控制器必须读取和修改例如512kB块(这是一个通常的数字,但是可能更大),然后再写回另一个块。虽然您原则上可以写入(但不能覆盖))闪存盘中较小的单元,则只能擦除巨大的块,这就是硬件的工作方式。这就是为什么SSD在进行大量顺序写入时性能要好得多的原因。


即使DLL被重定位,带回它的唯一需要的就是重定位的地址。重定位是确定性过程,可以重复。
MSalters 2015年

“聚写”?您是说“写”吗?
Peter Mortensen

3
@PeterMortensen:不,我的意思是真正的聚集写入(而不是分散读取)。这意味着在从多个位置收集数据的同时写入单个文件。您提供了一个结构数组,每个结构都包含一个起始地址和一个长度(严格的对齐要求)。操作系统将这些传递给控制器​​,而其余的则由硬件完成。
戴蒙2015年

1
@MSalters:但是重定位会创建页面的私有副本,因此很难确定是否对该私有副本进行了其他修改。与不需要修正的映射进行对比,并使用写时复制。如果进行其他修改,将有一个私人副本。如果没有,该页面仍将配置为CoW。
Ben Voigt 2015年

1
@MSalters这可能是确定性的过程,但这并不意味着休眠代码与链接程序在软件堆栈的同一层上运行。如果休眠是在内核层,而链接是在用户层,则休眠不能对链接器的功能进行任何假设。
卡巴斯德(Kasperd)2015年

10

它不会在休眠时转储整个RAM。

它已经在磁盘上复制了很大一部分RAM。这不仅可以使休眠迅速发生,而且可以使新程序可以快速使用内存(以便它们可以快速启动)。

因此,它只需要写入4GB的一小部分,就可以在10-15秒钟内完成。

微软

当RAM供不应求时(例如,Committed Bytes大于已安装的RAM),操作系统将通过复制未使用的虚拟内存页面到页面文件中,尝试使一定比例的已安装RAM可供立即使用。 。因此,该计数器不会达到零,并不一定能很好地表明您的系统是否缺少RAM。


2

除了上述所有以外,我认为还有其他一些因素在起作用。

一种是在复制文件时,必须读写文件。休眠仅需要写入文件。根据定义,它已经在内存中!

与此密切相关的是,在读取文件并同时写入文件时,为了节省内存,过程是:读取一个块,写入一个块,更新目录(以显示新的大小);读取一个块,写入一个块,更新目录。

每次您从磁盘的一部分移到另一部分时(例如,读取文件a写入文件b,写入文件b写入目录,并写入目录以读取下一块),磁盘必须寻找-移动磁头,让磁头稳定下来,等待磁盘的正确部分通过。这是固态磁盘的优点之一-搜索完全不需要时间。休眠时,数据是端对端写入的。休眠(交换)文件已预先分配,因此无需更新目录(您无需更改休眠文件的大小,只需更改内容即可)。

最后,您的计算机已暂停了所有其他任务-这只是它正在做的事情(我怀疑这会带来很大的不同,但是一定会有所作为!)。甚至诸如内存管理和任务切换之类的事情也被暂停。


它必将带来巨大的改变!
Lightness Races in Orbit

@LightnessRacesinOrbit:CPU争用几乎没有任何区别。缺乏I / O竞争很重要,但是这个答案已经表明,寻求会降低性能,而寻求而不是缺乏整体带宽是I / O竞争的主要问题。
Ben Voigt 2015年

@BenVoigt:是的,我同意。并且当您有40个进程都试图在磁盘上执行操作时,这将显着增加磁盘搜索。(tl;博士,我不是在谈论CPU争用)

@LightnessRacesinOrbit:即使在正常操作期间(进入和离开休眠状态之外的所有东西),这似乎也很不正常。我知道,当我遇到后台任务击中磁盘时,我会卸载吸盘并将其替换为仅在需要磁盘时才访问磁盘的东西。
Ben Voigt

@BenVoigt:这似乎不太可能。守护程序日志记录是最明显的反例,其次是ntpd的drift文件更新。我并不是说这两个例子在这里都有很大的作用,但是我认为没有后台任务可以自动访问磁盘是不合理的。
Lightness Races in Orbit

0

这可能是因为RAM的输入/输出速度比硬盘快得多,所以RAM可以像读取硬盘一样快地输出内容。

复制文件时,您还受到各种因素的限制-磁盘的速度,如果必须将其读入和读出到同一磁盘上,则将花费更长的时间,连接速度受限制(如果连接到外部驱动器),请检查磁盘没有覆盖任何东西等


9
但是操作系统仍然需要在磁盘上写入4GB RAM数据,这受I / O瓶颈的控制
编码器

同样假设参数合适,则意味着在休眠期间,磁盘的写入速度从40MB / s变为〜260 MB / s。可以正确吗?
编码器

1
可能-I / O瓶颈不应该太多,因为它只需要写入数据(可能存在适当的位置,因此它知道它不会覆盖内容以及将数据放置在何处,因此不会需要读取磁盘太多)。我可以在我的(Linux双启动)笔记本电脑上使用dd if=/dev/zero of=/tmp/output.img bs=8k count=256k并获取1862606848 bytes (1.9 GB) copied, 1.81605 s, 1.0 GB/s,因此这似乎是可能的(无论如何,我将添加Windows复制文件似乎花费不必要的时间)。
2015年

通过本地Internet复制文件时,还可以更快地进行传输。同样,它可能不需要复制RAM中的所有内容-从休眠状态唤醒时,RAM中的某些数据可能只是被缓存,不需要恢复系统。
2015年

我刚刚在系统上尝试了dd基准测试。它从未以超过52 MB / s的速度运行:/(旧机器),但是我相信“可能已经存在一些东西,因此它知道它不会覆盖内容和放置数据的位置,因此不需要读取磁盘太多”是提高速度的关键。
编码器
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.