读写SSD的注意事项
在几次对SSD硬盘进行fio的测试之后,我们采用了与传统硬盘相似的做法:依次采用了512K,1K, 2K,4K直至2M大小的数据对一块NVMe 企业级SSD进行读写测试,测试它的延时,并在不同的主机/操作系统上做出了2组数据,最终,得到了下图。
纵坐标表示延时的时常,单位是ns;暖色调表示对磁盘读的测试结果,而冷色调则是代表对磁盘写的测试结果。相信只要是明眼人一看就能明白这个数据似乎有很严重的问题: 对于小于4K的数据写入操作,系统会有惊人的延时,甚至延时的时长可以用秒来计算。令人吃惊的是两组数据的结果出入居然不大!
种种迹象说明,对于小文件的写入,SSD确实存在性能低下的问题。
另一个测试是连续数小时对SSD进行写操作,记录下每秒的操作数据,得到了如下图表:
不管如何测试,总会有一根断崖式的“跳楼线”出现在测试结果中。
这要从SSD的几个设计思路讲起。
我们知道,正常情况下,操作系统在format一块硬盘的时候,会有一个“簇”的概念。“簇”也就成了操作系统读写文件的一个最小单位。兴许是出于对这种“簇”概念的映射,SSD在内部也有簇的概念,我们称之为“page(页)”。SSD设备的读写都遵循以page为单位,也就是说:
- Reads are aligned on page size
- Writes are aligned on page size
- Pages cannot be overwritten
- Erases are aligned on block size
对应我的测试数据,当读取数据大小小于4K的page大小时,根据“1”,我们可以得知,SSD的主控芯片会将一个page的数据取出,然后截断到合适的大小即可,性能不会有太大的损失;而当写入一个小于page size的数据时,根据“2”可知,SSD的主控会等待数据填充至4K大小才能进行回填,性能自然会大幅下降。
看到这里,你一定会问:“对于现实中小文件的问题如何解决?”其实这个fio的测试数据是针对裸盘来进行的,对于已经被操作系统格式化的SSD只要保证它格式化时簇的大小是page的整倍数即可,而操作系统则可以完成对对于小于一个簇文件的自动缓存和填充。
对于数据的修改,根据3可知,SSD的主控芯片的操作并不是直接修改page的内容,而是将数据填充进一个新的page,然后SSD通过索引(register)位置的方式重新定义该文件的page。旧的簇会被索引标记为stale。
当SSD磁盘中 所有的page都被占用的时候,SSD就会自动触发垃圾回收机制(garbage collection)连续的stale pages会被合并成一个block并一次性清空。而这个清空的过程在实际状况下对于用户来说是自动启动且透明的,正常使用中我们是很难感觉到这个过程的存在,但在这个属于非正常使用的测试中,这个过程就会被反应成一个明显的“跳楼线”。
相较传统的物理硬盘,由于NAND芯片存在的擦写次数有限的缺陷,而且不能通过覆盖的方式更新文件。相较传统机械硬盘的读写模式,这样的读写操作比较复杂,但这从一定程度上减少了由于操作系统上部分文件过于频繁的修改(比如日志文件、swap文件等)导致的少数page迅速劣质化的问题。这种通过“擦除+写入”的实现方式由于擦除的耗时远远大于写入的过程,而且这个垃圾回收是针对于整个硬盘来说的,所以擦除的过程就成了整个测试中的瓶颈。
由于SSD需要定期触发GC进行垃圾回收,对于普通用户来说,长时间+大负荷的写入操作之后,尽可能的给SSD一个相对较为平静的时间段有利于SSD发挥更好的写性能。