【IT168 专稿】众所周知,固态硬盘(SSD)的性能会随时间的推移而下降,特别是早期推出的SSD更是如此,最新的SSD控制器通过各种手段降低了这个问题的影响,在这篇文章中,我们将一探SSD性能下降的根源,并介绍一些可行的解决方案。
SSD和性能
SSD性能下降问题与SSD的结构,以及文件系统和应用程序与它的交互有着紧密的联系,但几乎所有的问题都源于SSD的设计。在此前的文章中,我们已经介绍过了SSD构造的基本概念,写入SSD时,都是以一个页面为单元(通常是4KB),但SSD擦除时却是以块为单位,块的大小通常比页面的大小要大一些,一般来说,一块相当128个页面单元,即512KB,写入和擦除时使用的单位大小不同是理解SSD随时间推移性能下降的关键要素。下表从性能角度列出了单层单元(SLC)和多层单元(MLC)固态硬盘在读、写和擦除时的差异。
表1 SLC和MLC的I/O操作时间
从上表可以看出,对于SLC SSD,读操作比写操作要快10倍,而MLC则要快18倍,但更重要的是,擦除操作都很慢,如SLC SSD,擦除操作要比写入操作慢大约8倍,而读操作更是比擦除操作要快100倍,这就是为什么随时间推移,SSD速度会越来越慢的原因。
假设我们需要擦除一个块中的部分数据,例如其中一些页面,但前面我们已经提到,SSD是以块为单位进行擦除的,通常,会先将块中的数据从NAND芯片读出,写入缓存,随之擦除缓存中不需要的页面,再添加新的页面到缓存中,然后擦除SSD中的块,最后用缓存中的数据重新写入SSD中的块,因此即便是只需要简单的4KB变化,也要做大量的I/O操作,这过程被称为“读-修改-擦除-写”,简单说来就是读出数据-->擦除SSD-->在缓存内修改-->最后写入SSD。
这其中最大的问题就是擦除操作要比其它操作慢很多,从而影响了整体性能,由于应用程序可以同时写入多个数据块,文件系统也支持写入各种大小的数据块,数据将分布在很多块上,因此任何时候因数据变化或被擦除时,页面都需要更新,SSD就会执行一次“读-修改-擦除-写”操作,整体性能自然会下降。
SSD设计人员利用未使用的块池来缓解了这个问题,缓存中更新的块写入到包含在池中的干净块,“旧”块则标记为可擦除,在适当的时候进行擦除,通常都是在SSD垃圾回收期间进行擦除,通过这种设计减少了I/O操作的总体时间,因为擦除操作被延后了,但在垃圾回收期间就会消耗更长的时间来擦除块,SSD的总体吞吐量(性能)也会受到影响,最怀的情况是,一个简单的4KB写入操作可能会导致512KB数据写入,SSD中发生的写入数据量和应用程序产生的数据量的比值被称为写放大系数,在最好的情况下,写放大系数等于1,如4KB应用程序数据导致4KB SSD写入,在最坏的情况下,写放大系数等于128,即需要写入4KB,但最后写入了512KB,这和SSD的结构也有关系,一般常见的SSD,一个块大小是512KB,一个页面大小是4KB。
写放大系数和SSD、控制器、文件系统和应用程序紧密相关,因此无法准确给出特定SSD的平均写放大系数。写放大系数带来的问题是,随着时间的推移,文件系统的碎片会越来越多,数据散乱地分布在SSD块上,最后连一个干净的块也没有,一个简单的写操作都会有一个很大的写放大系数,最终就会导致性能下降。
除了影响性能外,写放大系数还会影响到SSD的使用寿命,SSD的写/擦除周期是有限制的,写放大系数大于1意味着需要写入更多的数据,因此会消耗更多的写/擦除周期,SSD的寿命因此也就减少了。
提高SSD写入性能的技术
不要因为写入性能问题就放弃SSD,SSD设计人员和工程师已经意识到问题的存在,并已经开始想办法减少其影响,其中一个解决办法叫做写合并。
写合并是一个简单的概念,它可以在SSD控制器上堆积更多的工作,控制器收集多个写入操作,然后一次性写入SSD,也就是说把多个小型相邻的页面写入操作组合到一起,形成一个大的写入操作,但这需要页面是相邻的,并且这些页面属于同一个文件,这样写放大系数就会接近于1,性能才会得到改善。
由于写合并技术有一些苛刻的条件,因此需要应用程序配合,确保文件是由整数倍块组成,避免产生碎片,这意味着任何数据擦除标志都将擦除整个块。但这样会有太多的工作要做,并且也只适合应用到SSD,传统的机械式硬盘就不适用了,并且和SSD的块大小也有关系,但无论如何,写合并技术绝对是个好主意,不过不是任何时候都能起作用。
另一个提高SSD性能的技术是预留一定数量的块,不将它们暴露给操作系统,例如,假设一块SSD总容量是750GB,只暴露65GB给操作系统,预留的块作为块池,增加周转页面数量,无形中保证了可用的干净块数量永远取之不尽,确保写操作不会再绕“读-修改-擦除-写”这么一个大圈子,至少它变成了“读-修改-写”过程,“旧”块被打上可擦除标记,等待合适的时机擦除,与此相反,如果没有干净块可用,控制器又必须返回到“读-修改-擦除-写”过程。
这个简单的概念叫做超量供应(或过度供应),它对SSD性能和寿命均有好处,如果SSD中的某个块比其它块的使用频率要高一些,那么它可以切换到预留池中的很少使用的块,有助于均衡SSD的整体损耗,超量供应的缺点是,你不能使用SSD上的所有空间。
另一个期待已久的技术叫做TRIM,当向一个尚未擦除的页面执行写操作时,性能是最低的,包含该页面的整个块都要读入到缓存中(读),新数据和块中已有的数据进行合并(修改),然后擦除SSD上的原始块(擦除),最后将缓存中的新块写入SSD(写),“读-修改-擦除-写”操作耗费的时间比直接写入到SSD要多得多。TRIM命令告诉SSD控制器,当某个页面不再需要时,就将其标记为可擦除,这个SSD控制器就可以直接向这个页面写入数据,从而避免掉完整的“读-修改-擦除-写”操作(只有写操作了),因此写性能将会得到改善,没有TRIM时,SSD控制器不知道何时擦除不需要的页面,控制器唯一能做的只有向干净的块写入数据。实质上,TRIM是给控制器提供了数据状态的暗示,相当于一个外挂,但TRIM也有助于提高SSD的性能和寿命。
但TRIM命令也有缺陷,首先,SSD控制器需要擦除打上标志的页面(如通过垃圾回收擦除),还是逃脱不了“读-修改-擦除-写”过程,SSD控制器会从包含数量最多的已标记页面的块擦除起,它也可能将这些块中已使用的页面放入其它块,以便擦除整个块,这就没有“修改-写”这两步了,但这个过程可能会使用块池中大量的块。第二个问题是,块池中的空闲块会越来越少,这会给SSD控制器带来更大的压力,因为TRIM命令会在减少的块池中标记页面,干净块会变得越来越少,因此在写数据时你很可能会遇到“读-修改-擦除-写”过程。
第三个问题与上面的几点都有关系,SSD控制器需要有足够的能力,时间和缓存启动垃圾回收过程,如果SSD被大量使用,包含由TRIM标记的页面的块会越来越多,如果SSD控制器没有时间执行垃圾回收,遭遇“读-修改-擦除-写”周期的可能性也越来越大,当然,SSD控制器设计人员可以在特定时间强制插入一个逻辑,执行垃圾回收,但结果还是一样:写性能会下降。
为了让TRIM更好地发挥作用,文件系统必须要知道页面什么时候删除,以及何时发送TRIM命令,操作系统必须要能够向磁盘控制器发送TRIM命令,磁盘控制器也必须理解这个命令,并采取相应的行动,Windows要先于Linux支持TRIM命令,但最近的Linux内核(具体来说就是2.6.33及更高版本)已经能很好地理解TRIM命令,并能够将其传递给磁盘控制器,许多文件系统也能理解TRIM命令,如EXT4和btrfs(从2.6.32开始)都能理解TRIM,其它文件系统也能理解TRIM。
与写合并和超量供应类似,TRIM解决写性能问题也不是功能较多的,如果你将太多的数据同时推向SSD,控制器可能很难跟上TRIM的节奏,如果你修改某个现有文件(没有事先擦除它),你仍然要走“读-修改-擦除-写”过程,这种情况TRIM也帮不上忙。
只要有“读-修改-擦除-写”这个周期,SSD随时间推移性能下降就是不可避免的,因为从根本上来讲,写发生在页面级别,而擦除是发生在块级别的,必然会产生写放大系数,如果写放大系数刚好等于1,表明应用程序请求写入的数据量刚好等于SSD的写入大小,一旦写放大系数大于1,SSD被迫要执行一些内务操作,这些额外的内务操作就会降低写入性能,也会减少SSD的使用寿命。
幸运的是,SSD设计人员和工程师已经展开了实际行动来解决这些问题,写合并、超量供应和TRIM命令都是这样的技术,它们都有助于减少“读-修改-擦除-写”周期对性能的影响,但我们也要知道这些技术都有前置条件,不是任何时候都能发挥作用。
此外,文件系统随时间推移也会产生大量的碎片,但目前不是每个设计人员和工程师都有能力解决这个问题。
在下一篇文章中,我们将会展示一些基准测试结果,看随时间推移SSD性能的下降情况,我们将用英特尔X25-E SSD(企业级)为例,结果会很有趣,敬请期待!