全部博文(51)
分类:
2010-03-04 15:39:18
由于这种代码也普遍具有情况下,很少有人敢于随 意更改预读的逻辑,它往往是微妙并快速的愤怒。吴峰光是敢于修改预读的勇士其中之一,他多年来 几次改进预读。他的 最新贡献 ,它试图以改善一般情况下预读的性能,同时也使得更加适应低内存的情况。
此修补程序的最大特点是如标题中所说的预读的大 小从128KB的增加为512KB。鉴于今天的文件和存储设备的大小,512KB的可能似乎有点小。但是预读也有费用,包括所需内存量来存储数据和 读文件所需的I / O数量带宽。如果一个较大的ReadAhead的缓冲区导致其他有 用的数据被调出,这可能导致系统性能的净损失,即使ReadAhead的数据都证明是有益的。大ReadAhead的行动将长期占用存储设 备,造成的I / O延迟增加。人们应当记得,ReadAhead的缓冲区有可 能是每打开文件描述符关联的 - 在系统中有数千个 。即使小的ReadAhead的数量增加,都会对 系统的行为产生很大的影响。
该数字确定为512k是通过同时运行使用旋转和 固态存储设备的一个广泛的一系列性能测试得出的。旋转磁盘,提高最大ReadAhead的大小为 512KB获得了近3倍的I / O吞吐量和可接受的I/ O延迟的进一步增加,如果再提高,吞吐量增加,但造成延迟增加的被认为是不可接受的。在固态器件的吞吐量增加较少(以百分比计算),但仍然 是可观的。
但这些数字显示了设备合理的性能提升。一个典型的USB thumb驱动器,没有一个合理的性能的设备,增加ReadAhead的大小可能真正遇到困难。为了解决这个问题,补丁集提出关于小型设备 ReadAhead的窗口大小的上限。对于一个2MB的设备(假设有这样的事情可以找 到),ReadAhead的是4KB的限制,为2GB的驱动器,限制为128KB的。 32GB以上的才能充分使512KB的ReadAhead的窗口生效。
这启发式并非十全十美。Jens Axboe ,一些固态器件的容量相对较小,但它们是可以很快的。这种设备可能无法很快执行,像他们可以拥有更大 ReadAhead的大小时一样。
此修补集程序的另一个的一部分是“上下文 ReadAhead”代码,试图阻止系统发起比它的内存可以处理的更多的ReadAhead。对于一个没有内存争用的典型的文件流,页面缓存 的内容可以可视化(以编辑器的蹩脚的绘画技巧)是这样的:
在这里,我们现在看到的是一个包含该文件的数据 页流表示,绿色的页是那些此时在页面缓存中的。几个最近消费的偏移后的页尚未被驱逐,完整的 ReadAhead的窗口正在等待应用程序过来消费它。
如果内存紧张,不过,我们可以找到更多这样的情况:
由于系统内存是你争我夺的,它已比以往更为侵略 性的将该文件的页赶出页面缓存。有历史上少得多,而且更重要的是,其中提出在经 ReadAhead的页数已被驱逐在应用能够真正加以利用它之前。这种颠簸这类行为是对系统性能有害的; ReadAhead的占用的内存被其他地方需要,并且数据将不得不在不久的将来第二次读入。显然,当这种行为被认为是,系统应该做的少 ReadAhead的。
颠簸的行为是很容易被发现;如果这些已经通过 ReadAhead读的页面被当应用程序试图以实际阅读他们时不在了,事情的进展将出现差错。当发生这种情况,代码将获得的内存量,可以安全 地使用通过计算历史页数量的估计(那些已经被应用程序消耗)的页面中的缓存中保留。如果一些历史信息保存着,历史的页数量作为一个 应该猜测什么样的ReadAhead的窗口的大小的可能值。
相反,如果有没有任何历史,ReadAhead的大小 减半。在这 种情况下,ReadAhead的代码,小心转移任何ReadAhead的仍然在内存中的页到LRU列表头,使不太可能,他们将立即被驱逐之前,在其使用 前。文件描 述符将被标记为“不死”,导致内核继续使用历史的大小作为未来ReadAhead的窗口大小引导。这反过来将导致窗口扩大和或缩小因为内存情况不 同。
ReadAhead 的变化可能很难进入主线。该启发式需要一定的技巧,而且正如莱纳斯已经 ,它可以很容易优化系统针对工作负载的子集: