李勇:我是在Novell实验室做与文件系统相关的东西。现在我是在维护两个系统,之前是做OPMI的开发。其实我还有一个角色就是北京Linux开发者的成员。
首先说一下通过重新排列原数据,提高文件系统的创建和删除工作,为什么要做这件事情。实际上从关系到我自己的问题引发出来的,第一就是 我要不要等一个小时清空我的垃圾箱。第二个就是在不升级硬件的前提下,有没有可能把速度再快一些。第三就是如果跑一些软件的话,那么有一些目录,如果不能 去格式化分区,能不能删除这些目录更快一些。那么这些问题本质是什么呢,这些问题的本质就是如果有大量的目录,在目录下又有大量的文件,那么或者更糟糕的 话,这些目录下的已经文件不是说一次创建的,可能是今天在这儿创建几个目录,明天在那儿创建几个文件,是这样交替创建的。那么在这种情况下,我们能不能让 文件创建得更快一些,还有就是删除文件的时候更快一些,这就是这个问题的本质。
我在尝试想解决这个问题的时候,就看到了 UAT4,在做这之前一下例子,在一个单独的目录下创建了50个空文件,这种文件去删的时候呢,我Reback模式下需要10分钟,但实际上这有多少数据 呢,所有这些东西加起来的数据不超过80兆,大概是70多兆,保守的说不超过80兆,这80兆数据写在硬盘上9秒钟就完了。大部分时间是在Sleep状 态。为什么这么慢呢,是因为顺序分配的,换句话说找到第一个空闲的槽就可以释放出来,但是为了提高路径查找的速度,它的目录文件是用哈西顺利做的。比如说 生成文件的时候,用ADJRMP,按这个样子来生成这么多文件,那么在这个图里面第一个彩色图对应的是这些文件的Anode表,在这个表里面的分裂,就按 照这个文件创建的顺序排列的,这个表很杂乱,过是访问文件的顺序,大家可以看到这个时候因为(哈西)顺序,就是分配化访问的顺序是不一样的,这个时候会有 大量的磁盘裙到,而且会有冗余。
就三个磁盘快可能需要提交24次指示,而且大家不要忘了,这只是目录里面的文件,那么我们在删除目录 里面文件的时候,我还要把目录的放到磁盘上去,这也是一个开销,这是导致速度慢的主要原因,这种说法准不准确呢,咱们就要找证据了。比如在刚才那个例子里 面,那些目录的话,咱们在删之前先把它拷到另外一个地方去,拷过去以后,把拷过去的目录删掉,这样比较一下就很明显,左侧是之前用的乱序升成的文件,右边 就是按照顺序拷过去的,这样时间差别就很大,大概速度可以快到15倍左右。那么这个提高的性能是非常的显著的。
这是在一个理想的情况 下,我们很难能碰到正好访问目录顺序的时候,正好是一样的,这是很难碰到的,但是至少这个测试显示出一个愿景,就是也许这样改进可以提高性能。我们可以看 到,通过刚才那些拷贝之后,原本排列是在第一行这个样子,那么经过重新拷贝之后排成了第二行的样子,这样就大量减少了磁盘裙道,而且在访问的时候同一个目 录下的,相靠近的有可能会被按照一种方式写到磁盘上去,而且这样减少了磁盘裙道的时间,而且也减少了IO的次数。刚才讲的只是在一个目录下有大量文件的情 况下。 那么还有一种情况就是我们有很多的目录,这种情况下问题就更糟糕了。
比如这个例子里面这些花花绿绿的,每种颜色代表 我在每一个目录下,不同的目录下的文件对应的Anode,如果按这种情况下做的话,我先创建了很多目录,每个目录里面有很多文件,这个综合加起来之后这个 顺序还是很糟糕的,所以这种情况下还是会有大量的额外的磁盘裙道和IO操作。面对这两种问题的解决办法呢,比较理想的解决办法有两个,第一个就是每个目录 下,当我们创建目录的时候,为这个目录的预留一段区域,当生成新文件的时候,是从为这个目录预留的区域里面找。那么这样就避免把不同目录下文件混合在一 起。这样就降低了对IO写的次数。但是这种方式当一个目录下的文件数太的时候对性能提高是没有帮助的,如果想要提高性能,那么就要把这个顺序排得尽量一 致。但是这种方式又对存在多个目录下有很多文件的删除帮助不大,所以要提高文件删除的性能必须把这两种办法合起来做。 但是我经过实验之后发现,想把目录下的文件的Anode顺序做成一致这是非常困难的。另外就是如果按照(哈西)顺序分配的话,有可能在预留区域内跳着分 配,这样会影响到磁盘操作。那么一个可行的方案就是先不要考虑目录下(Anode)顺序。预留区域不要太大。而且要尽量避免对文件系统在磁盘上的修改,还 有向前兼容EST23,这是什么意思呢,就是我拿一个EST2和EST3的分区过来,加一个选项就可以这样用。
用完了之后我把它 当作EST2和EST3运作还可以工作,不受影响。这本质就是新的对磁盘的(Anode)的分配器。我在网上发布的是第三版的补丁,我手里是第五版的补 丁,这包括注释,包括空行在里面的,代码是98行。比如说我现在创建4个目录,以前的会把这四个目录紧紧挨在最前面,现在我把中间空出一段,这就是预留的 区域。比如说我要给A下面分配一个文件的话,那么比如说我用小写的a代替,那么a就放在a的预留区,b就放在b的预留区,c就放在c的预留区。因为这是一 个尽量去尝试的分配机制,并不是硬把这些要预留给我,所以别人占了没关系,我再找。就这么一个分配策略,那么它对兼容性是没有问题的。 第一个不需要修改软件包。第二个就是为每一个目录预留的(Anode)的大小。
另外就是说可以用这种模式运行EST2和EST3。这 里面有一个地方可能会头疼,就是它会影响到EST4的一个性能,这个特性是为了减少FSK的时间,所以会EST每一个块组里面,标志没有被分配的标志,所 以它会标志在之前的地方,由于这个会跳着分配的,所以创建很多空目录的话,那么以前的也会被检查,这就是一个需要权衡的性能。
首先先 说一下垃圾箱的情况,那么我在做这个的时候,我先创建目录,添加文件的时候,先在每一个目录下添加一个文件,绕一圈之后再添加第二个文件,这样会把磁盘分 布打得很散,所以效果很好。实际情况不会这样的。如果有5万个目录,在每个目录下有15个文件,用刚才的方式做了之后,现在创建这些目录需要48 秒,加了目录之后会慢9%,这是很正常的,但是在创建文件的时候会快14.5%,在删除的时候会快56%。当目录删除的时候会快41%,仅仅这样重新改变 一下分配策略,什么都没有变的情况下速度会有很大的提高。但是有一个很有意思的事情,就是原来分配文件和创建文件的时候,应该速度会更慢才对,但是这出来 之后还会快一些,我测试最快的时候是100%,后来发现这个有很好的副产品,因为创建一个新的文件之后,新的离原来的附目录非常的近,这样的话这种方式反 而倒降低了IO操作的次数,和磁盘寻道的时间。
比如说现在有10几个CPU,这样共享一段存储磁盘,这么多CPU就可以很多人创建, 那么创建的时候会在每一个目录下产生大量的临时文件,这就和我的应用模式相符的。我在预留的时候为每一个目录预留64个,那么计算一下把这个软件包解压 缩,那么再计算一下过程,再比较一下目录预留和不预留两种性能,当有一个人用四个任务创建一个的时候,这两个性能差不多,但是当有8个人,为什么这么是1 呢,因为我的CPU只有两个,多了就跑不动了,当有8个人编辑8个的时候,大家看一下这个解压缩会慢一些,但是在编辑的时候会快20%。只是因为它在往磁 盘上写的时候,经过重新的布局,布局稍微改进了一点点,但是因为每一个目录下文件的数量差别非常大,从几百个到几个都有,因为我为每一个目录都预留相同的 大小,所以实际上在删除的时候性能差别非常大,因为删的时候非常方便。
第三个应用就是大家非常常用的,这个应用缺省的模式下会创建 16个一级目录,在每一个一级目录下创建256个二级目录,然后再二级目录下创建256个文件,这很整齐,我尝试用这个来试一下,把这些所有的文件充满需 要多长时间,第二个就是更新之前的文件,更新需要多长时间,然后再试一下把目录全部删掉需要多长时间,当创建这个文件的时间是相似的,但是更新的时候会快 6%,删除的时候会快86%。如果我有两个在操作的话,在同一个分区下操作两个目录,这时候创建目录会快10%,为什么会快呢,就是因为预留之后很整齐, 不会有额外的快的读写。第二个就是在更新的时候会快14.6%,最后删除这些文件的时候会快 43%。因为每个目录下的文件个数都非常整齐。
最后说一下为每个目录下预留(A node)不足之处,第一就是(A node)预留的空间大小是固定的。第二就是这个文件系统下对每一个目录预留的大小都是相同的,这是不太好的地方。第三就是在磁盘上(A node)顺序还没有跟随的(哈西)顺序。第四就是现在这些测试只能对有限的有帮助,比如说垃圾箱,CVS等等,因为它们的模式很像,就是会有很多目录, 每个目录都是交替者添加。
最后总结一下,磁盘上的原数据的分布,对于文件特别是小文件的创建和删除的性能是有影响的。第二个就是重新 排列文件系统的原数据的分布,是可以明显的提高小文件的创建和删除的性能。第三个就是静态的目录(A node)预留不能帮助每一个应用。所以就需要动态的目录做预留,所谓动态的就是会根据每个目录下文件多少不同,会动态的变更每一个目录预留的个数,这个 现在正在思考,即便这些都做到了,还有一个就是原数据的碎片整理,这个原数据的碎片整理是非常麻烦的,但是它又是非常需要的。谢谢大家。
提问者:你讲一下(必家数)李勇:这个比较灵活,它可以放在任何地方,但是对于EST的话,在格式化了之后,原数据放在什么地方就固定下来了,有一些优 化方式在EST下就不能用了,所以这个是针对,类似于这样的,这个(A node)必须在固定一个区域内的话是有用的。恩 提问者:我的问题是创建文件会不会变慢?
李勇:创建文件的话,如果这个文件尺寸非常大的话,那么创建文件主要性能影响不在于原数据, 而在于数据本身,这是没有优势的。如果这个文件的尺寸不大,而且在这个目录下创建文件的数量是适中的话,这个帮助是非常大的,如果这个目录下的文件尺寸不 大,数量巨大,那么目前的静态的目录下的(A node)预留是无能为力的,现在要做动态的预留。谢谢大家。