首页 > 代码库 > 为SSD编程(4)——高级功能和内部并行
为SSD编程(4)——高级功能和内部并行
原文 http://codecapsule.com/2014/02/12/coding-for-ssds-part-4-advanced-functionalities-and-internal-parallelism/
在这个部分,我将简要的介绍一些SSD的主要功能,如TRIM和预留空间。我同样会介绍SSD中不同等级的内部并行。
5. 高级功能
5.1 TRIM
让我们假设一个程序向SSD所有的逻辑块地址都写入文件,这个SSD当然会被装满。然后删除这些文件。文件系统会报告所有的地方都是空的,尽管硬盘实际上还是满的,因为SSD主控没法知道逻辑数据是什么时候被主机删掉的。SSD主控只会在这些逻辑块地址被复写的时候才知道这些是空闲空间。此时,垃圾回收进程将会擦除与这些文件相关的块,为进来的写操作提供空的页。其结果就是,擦除操作并非在知道保存有无用数据之后立刻执行,而是被延迟了,这将严重影响性能。
另一个值得关心的是,既然SDD主控不知道这些页保存有已删除的文件,垃圾回收机制仍然会为了损耗均衡而移动这些页上的数据。这增加了写入放大,并毫无意义地影响了来自主机的前台工作负载。
延迟擦除问题的一个解决方法是TRIM命令,这个命令由操作系统发送,通知SSD控制器逻辑空间中的这些页不会再使用了。有了这个信息,垃圾回收进程就会知道自己不必再移动这些页,并可以在任何需要的时间擦除它们。TRIM命令只会在当SSD、操作系统和文件系统都支持的时候才起作用。
TRIM命令的维基百科页面列出了支持TRIM的操作系统和文件系统[16]。Linux下,ATA TRIM的支持是在2.6.33版本加入的。尽管ext2和ext3 文件系统不支持TRIM,ext4 和XFS以及其他的一些是支持的。在Mac OS 10.6.8下,HFS+支持TRIM操作。Windows 7则只支持使用SATA接口的SSD的TRIM,使用PCI-Express的则不支持。
现在大部分的硬盘都支持TRIM,确实,允许垃圾回收尽早的工作显著地提升了将来的性能。因此强烈建议使用支持TRIM的SSD,并确保操作系统和文件系统级都启用了TRIM功能。
5.2 预留空间
预留空间只是简单的使物理块比逻辑块多,即为主控保留一定比例的,用户不可见的物理块。大多专业级SSD生产商已经包括了一些预留空间,通常是7~25%[13]。用户可以简单的通过创建比最大物理容量小的逻辑容量分区来创建更多的预留空间。例如,你可以在100G的硬盘上创建一个90G的分区,而把剩下的10G作为预留空间。即使预留空间在操作系统级是不可见的,但SSD主控仍然是可以看见的。生产商提供预留空间的主要原因是为了对付NAND闪存单元固有的兽兽门限制。不可见的预留空间的块将无缝的替换可见空间上的已耗损殆尽的块。
AnandTech有一篇有意思的文章显示出预留空间对SSD寿命和性能的影响[34]。在他们研究的硬盘上,结果显示出仅通过保证25%的预留空间(把所有的预留空间加在一起)就可以使性能极大地提升。在Percona的一篇文章中有另外一个有意思的结果,在他们测试了一块Intel 320 SSD,显示出当硬盘逐渐填满时,写入吞吐量将随之下降[38]。
这里是我的实验中发生的事情。垃圾回收是使用空闲时间在后台擦除页上不再使用的数据的。但既然擦除操作比写入操作的延迟更久,或者说擦除要的时间比写入长,在持续的重随机写入工作负载下的SSD将会在垃圾回收有机会擦除之前用尽所有的空块。此时,FTL将不能跟上前台的随机写入工作负载,而垃圾回收进程将必须在写入命令进来的同时擦除块。这就是在基准测试中SSD性能下降的厉害,而SSD显得性能超差的时候,如下图7所示。因此,预留空间可以吸收高吞吐量写入负载,起到缓冲的作用,为垃圾回收跟上写入操作并重新开始擦除无用块留够时间。预留空间需要多少大部分基于SSD使用环境的工作负载,和其需要的承受的写入操作的量。作为参考,持续随机写入的工作负载比较推荐使用大约25%的预留空间[34]。如果工作负载不是很重,大概10~15%估计够大的了。
预留空间对损耗均衡和性能表现是有用的
SSD可以简单地通过格式化时设置比最大物理容量小的逻辑容量来启动预留空间。余下的不被用户所见的空间仍会被SSD主控所用。预留空间帮助损耗均衡机制来对付NAND闪存单元的寿命限制。对于写入不是很重的工作负载,10~15%的预留空间足够了。对于持续的随机写入工作负载,保持25%的预留空间将会提升性能。预留空间将会扮演NAND闪存块的缓冲区的角色,帮助垃圾回收进程吸收写入峰值。
从此,同样可以推导出,预留空间甚至可能为不支持TRIM命令的环境提供更大的性能提升——注意我只是在这进行个假设,我仍然在寻找材料来支持这个观点。假设只有75%的硬盘空间可被操作系统使用,余下的25%留作预留空间。因为SSD控制器可以看见整个硬盘,尽管在某一时刻只有75%的物理NAND闪存被使用,但100%的块都在已使用、已废弃、已擦除三种状态中交替转换。这表示余下的25%物理闪存将可以安全的认为没有保存有数据,因为其并没有被映射到任何逻辑块地址上。因此,即使不支持TRIM,垃圾回收进程也能够提前擦除这些预留空间中块。
5.3 安全擦除
一些SSD主控提供ATA安全擦除功能,其作用是当硬盘处于意料之外的状态时恢复其性能。这个命令擦除所有用户写入的数据并重置FTL映射表,但这显然不能克服P/E循环有限造成的物理限制。尽管其功能上看上去非常有前途,但需要每个生产商争取的实现它。Wei等人2011年在他们关于安全擦除命令的review中显示,在他们研究的超过12个型号SSD中,只有8个提供了ATA安全擦除功能,而在这8个硬盘中,三个都有各种bug[11]。
对于性能的影响是很重要的,并且在安全方面更加重要,但我不想展开说。这里有几个Stack Overflow上的讨论可以解释关于如何可靠地删除SSD中的数据的细节。
5.4 原生命令队列(NCQ)
原生命令队列(NCQ)是SATA的一个功能,其允许SSD接受来自主机的多个命令,使SSD可以使用内部并行同时完成这些命令[3]。除了减少因为硬盘造成的延迟外,一些新的硬盘同样使用NCQ来应对来自主机的延迟。例如NCQ可以优先传入的命令来确保当主机CPU忙的时候硬盘总是有命令处理。
5.5 断电保护
无论是在家还是在数据中心,断电都是有可能发生的。一些生产商在他们的SSD结构中设置有超级电容,这个电容设计为存有足够提交总线中所有I/O请求所需的能量以防掉电。问题在于并非所有的SSD生产商都为他们的硬盘设置超级电容或者某种掉电保护,而有超级电容的不总是在说明书中提及。然后,和安全擦除命令一样,断电保护机制的实现是否正确,并且是否确实能够在掉电时避免数据损坏是搞不清楚的。
Zheng等人2013年的研究中测试了15个SSD,但没有透露品牌[72]。他们给硬盘各种各样的电源故障,发现测试的15个SSD中有13个最终丢失数据或者大规模的数据损坏。在另外一篇Luke Kenneth Casson Leighton写的关于电源故障的文章中显示出,测试的4个硬盘有3个最终都在不正确的状态,剩下的一个没有问题(是Intel的硬盘)[73] 。
SSD还是一个非常年轻的技术,并且我相信这些电源故障下造成数据损坏的阻力将会在接下来的产品中克服。然而现在,在数据中心配置不间断电源(UPS)可能还是应该做的。并且和任何其他存储解决方案一样,经常备份敏感数据。
6.SSD中的内部并行
6.1 总线带宽限制
因为物理限制的存在,异步NAND闪存I/O总线无法提供32-40 MB/s以上的带宽[5]。SSD生产商提升性能的唯一办法是以某种方法让他们的硬盘中的多个存储芯片可以并行或者交错。[2]的2.2节中有一个比较好的关于交错的解释。
通过组合SSD内所有层次的内部并行,不同芯片中的多个块可以作为一个叫clustered block(直译是集群块,但我感觉用簇比较亲切,本译文中所有的簇都是指它)东西同时访问。我不打算解释关于SSD内部并行的所有细节,因此我只简述一下并行的层次和簇。获取更多关于这个话题的信息,以及SSD内部并行的概括,这里的两篇论文是很好的开始[2, 3]。此外,一些高级命令如copyback和inter-plane transfer在[5]中有阐述。
内部并行
在SSD内部,数个层次的并行允许一次将数个块写入到不同的NAND闪存芯片中,这些块称为簇。
6.2 并行的多级别
下边的图6展示了NAND闪存芯片的内部,其组织为一种分级的结构。这些级别包括通道、封装、芯片、面、块和页。如[3]中揭示的,这些不同的层通过下边的方法提供并行
- 通道级并行 闪存主控和闪存封装之间的通信通过数个通道。这些通道可以独立或者同时访问。每个独立通道有数个封装共享。
- 封装级并行 一个通道中的不同封装可以独立访问。交错可以使命令同时在同一个通道中的不同封装中运行。
- 芯片级并行 一个封装包含两个或者更多的芯片,芯片可以并行独立访问。注:芯片通常也被称为核心(chips are also called “dies”)
- 面级并行 一个芯片包含两个或者更多的面。相同的操作(读、写或者擦除)可以在芯片中多个面上同时运行。面包含了块,块包含了页。面也包含了寄存器(小RAM缓存),其用在面级操作上。
图6: NAND 闪存封装
6.3 簇
译注: 本节标题原文是“clustered blocks”,词典上没有这个词(词组?),Google了也没有发现合适的翻译,其直译是“集群的块”或者“成簇的块”。因为这个“clustered blocks”和“簇”的英文“Data cluster”比较像,特性上也相似(都是若干存储单位的集合),决定将这个“clustered blocks”在本文中译为“簇”。但这个簇与机械硬盘的簇不是相同的东西,请读者注意分辨。如果有更为合适或者正规的翻译请告诉我。
从多个芯片中访问到的多个块被称为一个簇[2]。这个做法比较像RAID系统中的striping[1, 5]。
一次访问的逻辑块地址被分到不同SSD闪存封装中的不同芯片上。这归功于FTL的映射算法,并且这与这些地址是否连续无关。分割块允许同时使用多个通道来整合其带宽,并同样可以并行执行多个读、写和擦除操作。这即表示I/O操作按簇大小对齐来确保SSD中多个级别的内部并行所提供的性能能够最大程度的利用。