前段时间,在小米14的发布会上,雷布斯公布了名为"Xiaomi Ultra Space存储扩容"的技术,号称可以在512G的手机中再搞出来16G,256G的手机中再搞出8G。对于普通用户来说,能多得一些存储空间,无异是个很好的福利,不过也有网友说这是以损害存储使用寿命为代价的,那么真相到底如何呢?这篇文章我就从技术角度来给大家详细分析下。
认识闪存
首先让我们来了解一些手机存储的基本知识。
手机存储使用的是闪存技术,其本质和U盘、固态硬盘都是一样的。
在闪存中读写的基本单位是页(Page),比页更大的概念是块(Block),一个块会包含很多页。
虽然读写的基本单位都是页,但是写实际操作的很可能是块,这是为什么呢?
这要从删除谈起,在闪存中删除数据时不会立即删除页上的数据,而只是给页打上一个空闲的标签。这是因为谁也不知道这个页什么时候会再写入数据,这样处理起来比较简单快速。
再看写操作,如果写入分配的页是因为删除而空闲的,数据并不能立即写入,根据闪存的特性,此时需要先把页上之前存储的数据擦除,然后才能写入;但是闪存中擦除操作的基本单位是块,此时就需要先把整个块中的有效数据读出来,然后再擦除块,最后再向块中写入修改后的整块数据;这整个操作称为"读-改-写"。当然如果写入分配的页是空白的,并不需要先进行擦除,此时直接写入就可以了。
预留空间
小米这次抠出来的存储空间来源于一个称为"预留空间"的区域,它的英文全称是Over Provisio,简称 OP。
那么"预留空间"是什么呢?我将通过5个方面来介绍它的用途,让大家近距离认识下。
提高写入速度
在上面介绍闪存的基本知识时,我们谈到闪存的写操作存在一种"读-改-写"的情况,因为额外的读和擦除操作,这种方法的耗时相比单纯的写入会增加不少,闪存使用的时间越长,空白的空间越少,这种操作越容易出现,闪存的读写性能下降的越快。
为了提升写入的性能,我们可以先将新数据写入到预留空间,此时上层系统就可以认为已经写入完成,然后我们在后台将预留空间中的新数据和原数据块中需要保留的数据合并到一个新的数据块中,这样就避免了频繁的读-修改-写操作,从而可以大大提高写入速度。
垃圾回收和整理
在上面介绍闪存的基本知识时,我们还谈到删除数据并不是立即清除空间,而是给数据页打一个标签,这样做的效率比较高。这样做就像我们标记了垃圾,但是并没有把它们运走,时间久了,这些垃圾会占用很多的空间。这些垃圾空间就像一个个的小碎片,所以有时也把这个问题称为碎片化问题。
虽然我们可以通过"读-改-写"操作来重新利用这些碎片空间,包括通过异步的"读-改-写"操作来提升上层应用的写入效率,但无疑还是存在写入的难度,实际写入之前还是要先进行擦除。
为了解决上述问题,聪明的设计师们又想到了新办方法:让存储器在后台自动检测、自动整理存储中的数据碎片,而不是等到写入数据时再进行整理。
考虑到闪存的读擦写特性,当需要移除数据块中部分碎片或者将不同数据碎片合并时,就得把需要保留的数据先放到一个临时空间中,以免数据出现丢失,待存储中的数据块准备好之后再重新写入,预留空间就可以用作这个临时空间。
磨损均衡
闪存中每个块的写入次数都是有限制的,超过这个限制,块就可能会变得不可靠,不能再被使用。这就是我们通常所说的闪存的磨损。
为了尽可能延长闪存的使用寿命,我们需要尽量均匀地使用所有的闪存块,确保每个块的使用频率大致相同。这就是磨损均衡的主要目标。
假设我们发现块A的使用频率过高,我们需要将它的数据移动到没怎么用过的块B去,以达到磨损均衡的目的。首先,我们需要读取块A中的数据,然后将这些数据暂时存储到预留空间。然后,我们擦除块A,将它标记为空闲。最后,我们从预留空间中取出数据,写入到块B。实际上,磨损均衡的策略比这更复杂,不仅仅是看使用频率,还需要考虑其他因素,比如块的寿命,数据的重要性等。
可以看到,预留空间在这个过程中起到了临时存储数据的作用。
不过你可能会问,为什么不直接将块A的数据复制到块B,而需要一个临时空间?
这是因为在实际操作中直接复制块A的数据到块B会带来一些问题和限制。
假如直接进行这种数据复制,那么在数据从块A复制到块B的过程中,块A和块B中都会存在一份相同的数据,如果有其他进程在这个过程中访问了这份数据,可能会产生数据一致性的问题。此外,如果移动过程中发生意外中断,如电源故障,可能会导致数据在块B中只复制了一部分,而块A中的数据还未被擦除,这样就可能导致数据丢失或者数据不一致的问题。
而如果我们使用预留空间,也就是引入一个第三方,就可以缓解这些问题。我们先将数据从块A复制到预留空间,然后擦除块A,最后再将预留空间中的数据写入到块B。在这个过程中,我们可以借助预留空间来实现一些原子性的机制,来保证数据不会丢失和数据的一致性。
错误校正
预留空间还可以用来存储错误校正码(ECC)。如果在读取数据时发现有错误,可以用错误校正码来修复这些错误,提高数据的可靠性。
很多同学可能也不了解这个错误校正码的来龙去脉,这里多说几句。
我们知道计算机中的数据最终都是二进制的0和1,0和1使用硬件比较好表达,比如我们使用高电压表示1,低电压表示0。但是硬件有时候会出错,本来写进去的是1,读出来的却是0。为了解决这个问题,设计师们就搞出来个错误校正码,这个校正码是使用某些算法基于要存储的数据算出来的,存储数据的时候把它一起保存起来。读取数据的时候再使用相同的算法进行计算,如果两个校正码对不上,就说明存储的数据出现错误了。然后ECC算法可以通过计算知道是哪一位出现了错误,改正它就可以恢复正确的数据了。
注意ECC能够修正的二进制位数有限,因为可以修复的位数越多,额外需要的存储空间也越大,具体能修复几位要考虑出现坏块的概率以及数据的重要性。
坏块管理
当闪存单元变为坏块时,预留空间可以提供新的闪存单元来替代坏块,此时读取对应数据时不再访问坏块,而是通过映射表转到预留空间中读取,从而保证数据的存储和读取不受影响,提高了固态硬盘的可靠性和耐用性。
综上所述,预留空间在提升固态硬盘性能,延长其使用寿命,提高数据的可靠性等方面发挥着重要的作用。
小米的优化
根据公开资料,小米将预留空间的占比从6.9%压缩到了约3%。
那么小米是怎么做到的呢?以下是官方说法:
小米在主机端也基于文件管理深度介入了 UFS 的资源管理,通过软件实现"数据非必要不写入(UFS)",通过软件 + 固件实现"写入数据非必要不迁移",减少写入量的同时也实现了更好的 wear-leveling 和 WAF
还有一张图:
优化解读
这里用了一些术语,文字也比较抽象,我这里解读下:
UFS(Universal Flash Storage)即通用闪存存储,可以理解为就是手机中的存储模块。
"数据非必要不写入(UFS)"也就是先把数据写入到缓冲区,然后等收到足够的数据之后(比如1页),再写入闪存单元,这样就可以减少闪存单元的擦写次数,自然就能延长闪存单元的使用寿命,推迟坏块的产生。这个缓冲区类似于计算机的内存,如果突然掉电可能会丢失一部分数据,但是对于手机来说,突然掉电这个情况发生的几率极低,所以小米在这里多缓存点数据对数据丢失的影响很小,不过还是需要注意缓冲空间有限,这个值也不能太大,具体多少小米应该经过大量测试之后做了评估。
"写入数据非必要不迁移" 没有细说怎么做的,大概率说的是优化磨损均衡、垃圾回收和整理策略,没事别瞎整理,整理的时候尽量少擦写,目的还是延长闪存单元的使用寿命。
"增加坏块预留" 小米可以根据用户的使用情况调整坏块预留区的大小,比如用户是个重度手机使用狂,他用1年相当于别人用4年,小米系统就会增加坏块预留区,以应对擦写次数增加带来的坏块几率增加。注意这个调整是在云端实现的,如果手机不联网,这个功能还用不上。
wear-leveling:就是上面提到的磨损均衡,小米优化了均衡算法,减少擦写。
WAF:写放大,Write Amplification Factor,缩写WAF。写放大就是上面提到的"读-改-写"操作引起的,因为擦除必须擦掉整个块的数据,所以上层系统只需要写一个页的情况下,底层存储可能要重写一个块,从页到块放大了写操作的数据量。因为闪存的寿命取决于擦除次数,所以写放大会影响到闪存的使用寿命。
概括来说就是,小米从存储的预留空间中抠出来一部分作为用户存储,不过预留空间的减小,意味着坏块管理、错误纠正等可以使用的空间变小,这些空间变小会减少存储的使用寿命,所以小米又通过各种算法延缓了手机存储的磨损速度,如此则对大家的使用没有什么影响,而用户又能多得一些存储空间。
小米的测试结果
对于大家担心小米手机存储的寿命问题,小米手机系统软件部总监张国全表示:"按照目前重度用户的模型来评估,在每天写入40GB数据的条件下, 256GB的扩容芯片依然可以保证超过10年, 512GB可以超过20年,请大家放心。"
同时一般固态硬盘往往都拥有5年的质保,而很多消费者往往会5年之内更换手机。因此按着这个寿命数据来看,普通消费者并不用太担心"扩容芯片"的寿命问题。所以如果你的手机用不了10年,可以不用担心这个问题。
当然更多的测试细节,小米并没有透漏,比如读写文件的大小等。不过按照小米的说法,存储的供应商也做了测试,没有什么问题。这个暂时只能相信小米是个负责任的企业,做好了完备的测试。
最后小米搞了这个技术,申请了专利,但是又把标准和技术方案贡献给了UFS协会,同时还要求存储芯片厂商设置了半年的保护期,也就是说技术可以分享给大家,但是请大家体谅下原创的辛苦,所以半年后其它手机厂商才能用上。
大家猜一下半年后其它手机厂商会跟进吗?
关注微/信/公/众/号:萤火架构,提升技术不迷路。