程序预读(prefetch,在Linux中也称为预读,read ahead)是一种用于晋升程序读性能的技术,用于放大存储设备和应用程序之间微小的效率差距。Linux内核在通用预读框架中执行程序文件预读,它被动拦挡VFS层中的文件读取申请,并将程序的申请转换为异步预读申请,为行将到来的申请引入数据块,并在大块中进行。

I/O预读背景

带宽和提早是I/O性能的两个次要衡量标准。对于这两个规范,在磁盘、内存和处理器之间存在着微小的性能差距。例如,当今的DDR5内存的实践带宽通常为40GB/s以上,响应工夫为纳秒级,而一个希捷(R) 7200转SATA磁盘的最大继续传输速率为200MB/s,均匀寻道工夫为5ms。两者之间存在的性能差距,带宽相差数百倍提早相差10^7倍

I/O提早是影响磁盘I/O性能的一个次要因素,能够用一个简略的I/O模型来近似。典型的磁盘I/O有两个步骤:首先,磁头挪动到数据轨道,期待数据扇区在其下旋转;其次,开始数据读取和传输。相应的有两个操作工夫:均匀拜访工夫,典型值为8ms;数据传输工夫,大抵等于I/O大小和磁盘继续传输速率的乘积,对于目前的一般磁盘(HDD),均匀传输速率为200MB/s。

在一个残缺的I/O周期中,只有数据传输工夫能力真正利用磁盘数据通道。I/O大小越大,在数据传输上破费的工夫就越多,相对来说,在搜寻上节约的工夫就越少,因而咱们能够取得更多的磁盘利用率和I/O带宽。下图反映了上述磁盘I/O模型和代表性参数值的相关性。I/O预读的次要目标是将图中磁盘的工作点从左向右挪动,从而取得更好的I/O带宽。

应用较大的I/O大小能够更好地利用磁盘

随着数字信息的激增,提前读算法依然在持续施展重要作用。固态磁盘极大地缩小了耗时的寻道工夫,然而依然存在不小的拜访提早。特地是SSD存储器基本上是由许多并行操作的芯片组成,较大的预读I/O将可能利用并行芯片的劣势。从SSD存储取得齐全性能所需的最佳I/O大小与旋转介质不同,并且因设施而异。因而,即便是在SSD上,I/O预读也很要害。

总之,有程序拜访模式的中央,就有I/O预读的市场。无论是基于机械磁盘还是固态磁盘。

I/O优化和预读

从利用角度,目前业界有四种根本的I/O优化策略:

防止从存储设备上IO。最好的抉择是完全避免或尽可能减少存储介质拜访频率。这能够通过文件内存缓存来实现。预读擅长于将小的读申请转换为大的读申请,这无效地缩小了存储介质拜访的数量,从而升高了昂扬的查找老本。具体的例子是家喻户晓的Linux VFS(虚构文件系统)挂载选项noatime和relatime,用于打消由mtime更新触发的不必要的向存储设备的写操作。

程序化。程序拜访能反对程序预读并最大化磁盘性能利用率。对于并发程序拜访,预读在将交织的小I/O聚合为大I/O方面起着至关重要的作用。对于非程序拜访,通过应用智能磁盘布局治理、告诉式预读、I/O排队和调度等技术,将磁盘寻址提早最小化。举几个通过程序化进行性能优化的例子:SCSI磁盘的TCQ(标记命令队列)和SATA磁盘的NCQ(本机命令队列);ext4/xfs的提早调配和预调配;xfs中的回写集群等。

异步化。异步拜访通过流水线化处理器和磁盘操作,暗藏应用程序的I/O提早的形式来进步I/O效率。AIO、非阻塞I/O、回写和预读是异步I/O的常用工具。

并行化。聚合多个磁盘的容量和带宽可晋升整体IO性能曾经是分布式存储的共识。在传统的RAID层之外,以zfs和btrfs为例的新兴文件系统能够本人治理大型磁盘池。另一方面,在SSD外部应用了设施级并发解决。例如,英特尔在其SATA固态硬盘中开拓了10个并行的NAND闪存通道,可提供高达500MB/s的读取带宽和50000以上的 IOPS。并发I/O申请和并行数据传输是上述并行零碎的I/O吞吐量的要害。被动预读在这个畛域中扮演着重要的角色:它们通常须要大型的异步预读I/O来填充并行数据通道。

预读有助于实现I/O异步和并行

显然,预读在四种I/O优化策略中都扮演着重要的角色。预读能够为应用程序、存储设备和存储池,甚至处理器资源带来性能改善。通过屏蔽较高的I/O提早,应用程序能够运行得更快更晦涩。大块I/O能够更好地利用磁盘,能够更好地并行化,也有助于摊薄整个I/O门路的解决开销。

预读的根本办法

预读算法能够是预测式的,也能够是利用被动告诉式的。预测式算法试图基于过来的I/O预测将来将被拜访的I/O块,自动自发地执行预读决策,对下层利用是通明的,这种形式对算法的要求较高,存在命中率的问题。最胜利的一种做法是程序预读,这始终是操作系统的规范实际。新型的预测式预读能够基于灵便的AI算法或统计,晋升预读数据的命中率。

利用被动告诉式预读,应用来自各个应用程序对于其将来I/O操作的提醒,提醒能够由应用程序显式地管制。

缓存是另一种普遍存在的性能优化技术。共享预读内存和缓存内存是一种常见的做法,这为预读和缓存之间的交互关上了大门。

预读的设计衡量

预读大小对I/O性能有很大影响,被认为是次要的预读参数。在确定预读大小值时,必须在吞吐量和提早之间进行衡量。个别的领导准则是:预读的大小应该足够大,以提供良好的I/O吞吐量,但同时也要避免预读块过大,从而防止不必要的过长的I/O提早。

不同的存储设备、磁盘阵列配置和工作负载具备不同的最佳预读IO大小。某些应用程序(如对I/O提早不敏感),能够平安地应用较大的预读大小;其余利用可能对I/O提早敏感,这时应该应用更激进的预读I/O大小。

除了吞吐量和提早之间的衡量之外,预读命中率是另一个常见的设计思考因素。为了放弃较高的预读命中率,须要应用自适应预读大小。这是因为,即便咱们确信应用程序正在进行程序读取,咱们也无奈预知程序读操作还会继续多久。例如,应用程序可能从头到尾读取一整个文件,而另一个应用程序只拜访这个文件中的前两个page。

侥幸的是,常见的I/O行为大多是能够推断的。首先,行将要读取的page数(不思考文件完结的状况)和已拜访的page数通常是正相干的。其次,读取的大小越大,反复的可能性就越大。因为较大的预读大小意味着研发人员要对预期的长时间预读进行优化。依据以上两条教训规定,能够预计以后拜访模式反复的可能性,并据此计算自适应预读大小。

进步预读命中率是预读算法设计的一个次要指标。低命中率意味着内存和磁盘I/O资源的节约,这样节约是昂扬和不可承受的。传统的预读算法偏向于只对严格的程序读取进行预读。它们对预读大小采纳激进策略,并采纳程序检测,以寻求较高的预读命中率。

然而,随着计算机硬件的疾速倒退,咱们也面临着新的束缚和要求。内存和磁盘的带宽和容量都有了很大的进步,但磁盘拜访工夫依然很慢,并且越来越成为I/O瓶颈。因而,预读命中的益处就减少了,它减少了预读的重要性,意味着底层存储应该更被动地进行预读。

因而,即便就义肯定的预读命中率,它也能够进步总体I/O性能。工作负载的预读命中率取决于IO模式识别和这种特定模式运行时长评估的准确性。

YRCloudFile Linux客户端预读

YRCloudFile Linux客户端预读,对接了Linux内核预读机制,专门针对程序读的性能进行优化。

下图为用FIO测试工具,对小文件程序读、大文件程序读场景进行测试,在Linux客户端预读开启和敞开状况下,不同内核版本的不同性能体现。

预读对4K/1M程序读性能的影响

从理论测试数据看,YRCloudFile Linux客户端预读性能开启与否,在不同内核版本的下,程序读性能晋升2.5-20倍不等。

YRCloudFile Linux客户端预读机制很好地解决了文件程序读速度慢、拜访提早高的问题,帮忙AI利用,影视内容制作等利用轻松应答海量文件程序读拜访的性能挑战。

不可能有一种技术满足所有的需要,业务软件是单线程还是多线程、IO特点是一次写屡次读还是一直追加写、是程序读还是随机读等等。焱融技术团队通过一直的与客户的交换、碰撞,对不同场景,不同类型的利用进行剖析,一直推出新的性能,让YRCloudFile更趋于成熟,帮忙用户成就大数据与人工智能时代的企业外围竞争力。

参考资料
1.https://bootlin.com/pub/readahead/doc/ols2007-readahead-paper.pdf\
2.https://engineering.purdue.edu/~ychu/publications/tc07_pref.pdf\
3.https://pdfs.semanticscholar.org