转发了微软中国MSDN的微博:#Connect# 跨平台Linux、iOS、Windows,.NET程序员雄起!微软兑现其支持跨平台开发的承诺,今天宣布全部.NET服务器端框架将走向开源,包括ASP.NET、.NET编译器、.NET核心运行环境、框架和库,让开发者能够使用.NET技术在Windows、Mac和Linux上开发应用!(发表于11月14日 20:59,来自Robbie Mosaic的微博评论(1) 转发

ReadyBoost–Robbie 的基准测试

2012-04-14
Robbie Fan 范德成

背景:我以前对 Windows Vista ReadyBoost 并没有多少信心。我曾认为它没有达到我的期望,因为我粗略的性能对比测试显示在跑了一个内存消耗程序把其他进程的工作集清出内存之后,ReadyBoost 并没有出现明显的效用。然而,这回我对它的理解改进了,认为它虽然看上去没有 Windows 7 的 ReadyBoost 那么好,但它仍有它的效用。

配置:笔记本电脑,内置 120GB 的(每分钟)5400 转硬盘,连续读取性能 50MB 每秒。Intel 酷睿 2 双核 CPU 运行于 800MHz(省电模式)。3GB 内存。4GB 的 ReadyBoost 缓存设置于一只金士顿 16GB U 盘,其连续读性能为 20MB 每秒,连续写性能为 7MB 每秒。

基准测试方法:我使用两个各消耗 1GB 内存的程序。每个程序本质上分配 1GB 内存,读写每一个内存页,然后释放掉这些内存。它们在一开始被设为反复启动。当运行了一定次数后(20~30 次),我关闭这些内存消耗程序并开始记秒数。等到磁盘活动恢复正常(资源监视器中平均磁盘时间小于等于 30%,或任务管理器中缓存大于等于 300MB)后停止记时。

结果:

  • 不用 ReadyBoost:155 秒
  • ReadyBoost 开启但没有很多预填充:119 秒
  • ReadyBoost 开启并有足够的预填充:35 秒

资源监视器,通过它可以看到内存消耗程序的行为

解释一下:Windows 实现了一种叫进程工作集的概念。一个进程有 4GB(或 x64 上是 16TB)虚拟地址空间,其中一部分被映射为 4KB 大小的内存页。Windows 不断跟踪最近被使用的页面和最近较少使用的页面,并试图把尽可能多的页面留在物理内存里。最近较少使用的页面被换出到硬盘上。注意虚拟地址空间可能包含匿名内存(比如 C 语言程序中的全局变量和用 malloc 函数分配的内存),它用页面文件来作备用存储,还可能包含内存映射文件(包括可执行文件的正文)。只要一个页面自上次被加载到物理内存后已被修改过(或者它是一块新分配的内存,之前从没在磁盘上存在过),一个换出操作将包含向页面文件或内存映射文件写入的操作;其他情况下它不做任何事情。

当进程访问一个在物理内存中不存在的页面时,Windows 必须做一次换入操作。因为之前换出的页面是基于使用情况的,它们很有可能分散在地址空间的各个位置(当考虑到动态内存分配时尤其如此)。另一个相对次要的问题是有时候页面文件中的空闲空间不是连续的。由于前述两个问题,换入可能带有许多非常随机的读操作。这样一来我们就遇到了一个当代硬盘的性能瓶颈:寻道时间 + 旋转时间。每个随机读操作都需要一次磁盘寻道和旋转,对硬盘来说这个时间是约 10~20 毫秒。即使是每分钟 7200 转的硬盘,时间还是超过 5 毫秒。Windows 可以通过预读页面文件中连续的几个页面来优化换入操作。假定在最坏情况下,每个换入的预读操作都没有命中,并假设 10 毫秒读一次,那么每秒将有 400KB 的内存换入。通常情况比这好些,但是据我从资源监视器中观察的结果来看,平均速度还是在每秒 2MB 以下。

性能监视器监视 ReadyBoost,显示出未很好地填充时的状态

相反,使用闪存存储器工艺的 U 盘有着高得多的随机读性能,大约每次 1 毫秒(虽然比物理内存还是慢得多)。因此我们可以期望用它来加速换入操作。然而,它无法给换出操作明显加速,因为它的顺序写速度仅为 5~10MB 每秒。由于它可移除,而且不同品牌和型号的产品质量也有高低,它并不是页面文件的理想替代品。因此 ReadyBoost 把它用作性能加速器,但却不是页面文件的存储器。

Windows Vista 的闪存设备利用方案包含两个部分:Superfetch 和 ReadyBoost。ReadyBoost 缓存的填充有两个途径:由 Superfetch 填充,或保存换出页面和写入磁盘的内容。Superfetch 填充是 ReadyBoost 缓存的主要组成部分。Superfetch 是一个“预测”将来会用到的页面的技术。作为微软研究院(Microsoft Research)的理论研究转化出来的产品,它使用人工智能来分析页面的访问形式,从而按页面可能被访问的概率排序把页面保存在物理内存中或闪存中。将来最可能被访问的页面放在物理内存中,而被访问的可能性低些的页面放在闪存中。

你也许知道,闪存设备的随机写性能比较低。这是因为每次一个地址要被写入时,整个闪存块(有些情况下大至 2MB)需要被读一次(并备份),擦除再被写入。ReadyBoost 为了高效地写入闪存,它必须尽可能缓冲并序列化写入。由于记录的页面相当随机,从设备的读取也将很随机,但这正是闪存的优势所在,故不存在问题。ReadyBoost 在闪存设备被插入时会预先测试它,只要它的 4KB 随机读性能超过 2.5MB 每秒并且 512KB 随机写性能超过 1.75MB 每秒,就认为它是可用于加速的。ReadyBoost 使用数据压缩来更有效地利用缓存空间。

性能监视器监视 ReadyBoost,显示出已很好地填充后的状态

我的性能测试显示 ReadyBoost 缓存在反复运行内存消耗程序的情况下能被很好地填充。“很好地填充”的定义是:经常使用的页面在缓存中。我对测试结果的解释如下:第一次启动内存消耗程序时,假设有 1.4GB 工作集在物理内存中,那么其余的 1.6GB 物理内存将包含相对较少可能被访问的页面。ReadyBoost 缓存将被填充进比那 1.6GB 物理内存中的页面更少可能被访问的页面。所以,如果我的内存消耗程序把 1.6GB 缓存和 0.4GB 工作集清出物理内存,ReadyBoost 也不太可能在这些页面被换入时帮上什么大忙。

然而,当内存消耗程序反复启动后,将发生两件事情。第一,Superfetch 将随机地遇到内存消耗程序占据了物理内存,而 Superfetch 无法把页面填充到其中的情况。第二,0.4GB 的工作集将周期性地被清出物理内存,从而 Superfetch 将试图把它们取回到缓存中。这样一来,这 0.4GB 就有一定概率被保存到 ReadyBoost 缓存中。从而,在 Superfetch 填充了足够长的一阵子之后,它们很有可能就在 ReadyBoost 的缓存中,并能被快速地加载回来,而不是慢吞吞地从硬盘上读取。这是对我的测试结果的一个解释。

在我使用了 ReadyBoost 足够长的一段时间,并观察了它的性能图形(命中读取字节/秒 和 顺序 IO 放弃/秒)之后,我想说一个小现象:ReadyBoost,或严格地说是 Superfetch,不会预取“数据映射表”,就是说文件系统结构(MFT(主文件表),目录(文件名)等等)。这些数据仅由缓存管理器在物理内存中进行缓存。

作为对本文的总结,我对如何利用好 ReadyBoost 的建议:当物理内存紧张时,可能的话多买点内存条并插上。然后拿一个快速的 U 盘来使用 ReadyBoost(直接插电脑 USB 口,不要用延长线或集线器)。避免把各种各样的数据同时塞进内存。当你的笔记本电脑使用电池供电时,启用 ReadyBoost——它会帮你节省电量。如果你的电脑有一个固态硬盘(SSD),就不要用 ReadyBoost 和 Superfetch 了。