微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 如何让linux服务器磁盘io性能翻倍

如何让linux服务器磁盘io性能翻倍

时间:09-12 来源:互联网 点击:

一 机械磁盘的io的速度主要受“寻道速度”的限制,所以在访问小文件时io性能会极差。如果不在乎成本,可以通过使用固态硬盘来解决这个问题。

二 linux的主流文件系统(如ext4等),在文件系统持续比较满,且需要经常删改文件时,会产生大量文件碎片。在我开发的一款代理服务器中,磁盘长期满负荷运转,运行一个月后文件碎片大约会让io性能降低至只剩20%-30%

这一期我们来看一下有哪些办法可以减少linux下的文件碎片。主要是针对磁盘长期满负荷运转的使用场景(例如http代理服务器);另外有一个小技巧,针对互联网图片服务器,可以将io性能提升数倍。

如果为服务器订制一个专用文件系统,可以完全解决文件碎片的问题,将磁盘io的性能发挥至极限。对于我们的代理服务器,相当于把io性能提升到3-5倍。

在现有文件系统下进行优化

linux内核和各个文件系统采用了几个优化方案来提升磁盘访问速度。但这些优化方案需要在我们的服务器设计中进行配合才能得到充分发挥。

文件系统缓存

linux内核会将大部分空闲内存交给虚拟文件系统,来作为文件缓存,叫做page cache。在内存不足时,这部分内存会采用lru算法进行淘汰。

通过free命令查看内存,显示为cached的部分就是文件缓存了。

如何针对性优化:

lru并不是一个优秀淘汰算法,lru最大的优势是普适性好,在各种使用场景下都能起到一定的效果。

如果能找到当前使用场景下,文件被访问的统计特征,针对性的写一个淘汰算法,可以大幅提升文件缓存的命中率。

对于http正向代理来说,一个好的淘汰算法可以用1GB内存达到lru算法100GB内存的缓存效果。

如果不打算写一个新的淘汰算法,一般不需要在应用层再搭一个文件cache程序来做缓存。

最小分配

当文件扩大,需要分配磁盘空间时,大部分文件系统不会仅仅只分配当前需要的磁盘空间,而是会多分配一些磁盘空间。这样下次文件扩大时就可以使用已经分配好的空间,而不会频繁的去分配新空间。

例如ext3下,每次分配磁盘空间时,最小是分配8KB。

最小分配的副作用是会浪费一些磁盘空间(分配了但是又没有使用)

如何针对性优化:

我们在reiserfs下将最小分配空间从8KB改大到128K后提升了30%的磁盘io性能。

如果当前使用场景下小文件很多,把预分配改大就会浪费很多磁盘空间,所以这个数值要根据当前使用场景来设定。

似乎要直接改源代码才能生效,不太记得了,09年的时候改的,有兴趣的同学自己google吧。

io访问调度

在同时有多个io访问时,linux内核可以对这些io访问按LBA进行合并和排序,这样磁头在移动时,可以“顺便”读出移动过程中的数据。

2.6内核有四种不同的排序算法,有些侧重于io性能最大化,也有一些侧重于调度的公平性,大致上的原理都类似于电梯排序。

SATA等磁盘甚至在磁盘中内置了io排序来进一步提升性能,一般需要在主板中进行配置才能启动磁盘内置io排序。linux的io排序是根据LBA进行的,但LBA是一个一维线性地址,无法完全反应出二维的圆形磁盘,所以磁盘的内置io排序能达到更好的效果。

关于LBA请参考上一期博客,http://blog.chinaunix.net/uid-29873073-id-4514435.html

如何针对性优化:

io访问调度能大幅提升io性能,前提是应用层同时发起了足够的io访问供linux去调度。

怎样才能从应用层同时向内核发起多个io访问呢?

方案一是用aio_read异步发起多个文件读写请求。

方案二是使用磁盘线程池同时发起多个文件读写请求。

对我们的http正向代理来说,采用16个线程读写磁盘可以将性能提升到2.5倍左右。具体开多少个线程/进程,可以根据具体使用场景来决定。

小提示:

将文件句柄设置为非阻塞时,进程还是会睡眠等待磁盘io,非阻塞对于文件读写是不生效的。在正常情况下,读文件只会引入十几毫秒睡眠,所以不太明显;而在磁盘io极大时,读文件会引起十秒以上的进程睡眠。

详见内核源代码do_generic_file_read会调用lock_page_killable进入睡眠,但是不会判断句柄的非阻塞标志。

预读取

linux内核可以预测我们“将来的读请求”并提前将数据读取出来。通过预读取可以减少读io的次数,并且减小读请求的延时。

如何针对性优化:

预读取的预测准确率是有限的,与其依赖预读取,不如我们直接开一个较大的缓冲区,一次性将文件读出来再慢慢处理;尽量不要开一个较小的缓冲区,循环读文件/处理文件。

究竟开多大缓冲区合适,要根据具体使用场景下的内存/磁盘io压力来决定。

虽然说“预读取”和“延迟分配”能起到类似的作用,但是我们自己扩大读写缓冲区效果要更好。

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top