首先大家都很熟悉SSD的Trim指令,是文件系统用来告诉闪存主控哪些数据块已经不在使用中,可以被擦除回收以供后续更加快速地写入,并且可以被用于磨损均衡。 一般来说U盘均不支持Trim指令(除非是SSD主控桥接并且支持Trim),所以很多U盘在使用一段时间后常常会遇到非常严重的掉速现象,这是因为所有的闪存块都被写入过数据,但是文件系统无法告知主控哪些数据块里面是可用信息,哪些是可以回收的块。这样会给磨损均衡带来极大的问题,因为在主控看来所有块都是存着数据的而不知道哪些块里的文件已经被删除。这样就迫使主控在收到写入某个块的命令时现场擦除后写入,因此可能会产生很大的性能损失。如果在写入时因为写入块的被擦写次数过多而触发了磨损平衡,则速度会进一步受影响。我以前的一个闪迪CZ800经过几个月的使用速度肉眼可见的越来越慢,猜测就是因为无法trim/磨损平衡而触发GC导致严重掉速,甚至时不时出现掉速到500KB/s以下的情况。 但是很多人可能不知道的是,SD卡实际上是支持类似Trim的功能的。挂载在PCI上的mmcblk设备(笔记本自带读卡器,树莓派,单片机等等,USB读卡器不可以)都支持通过MMC命令对SD卡进行各种操作(比如另一个老哥通过CMD56自定义命令来查询SD卡的寿命和写入均衡信息)。 这里我们随便选一个金士顿SDCIT/64GB的datasheet为例,可以看出SD卡驱动是通过CMD32、CMD33、CMD38来擦除某个块的: 而且和CMD56查询SMART信息不一样的是,这些命令所有SD卡都是支持的。所以host至少有办法通知SD卡哪些数据块可供回收。但是,这并不保证某个主控真的会去回收而不是直接无视命令。 在Linux电脑或者树莓派上,可以通过fstrim命令对某个已经挂载的文件系统进行trim: sudo fstrim -v /path/to/filesystem 执行结束后会返回trim掉多少数据块的信息,例: 其中/path/to/filesystem是指向文件系统的路径,执行该指令后会对该文件系统进行trim并对不在使用中的块发送CMD38擦除指令。 如果SD卡里没数据,可以使用blkdiscard命令一次性trim掉所有的数据块: sudo blkdiscard -f /dev/mmcblk 但是!所有以上命令都只是起到了标记无用块/通知SD卡主控的作用,而不是当场对所有数据块现场擦除。即使我们有办法在软件层面上通知主控,如果SD卡主控选择无视命令那也没有用处。所以我想做一些简单的测试看看SD卡会对discard命令做何反应。 首先测试一张慧荣主控使用MLC芯片的二手江波龙老卡,通过另一位老哥的方法读取其寿命与擦写信息: 可以看出这张卡已经被平均擦鞋了450次。 当这张卡经过长久使用,所有块上都充满了脏数据,即使删除所有文件之后反复做速度测试也会非常稳定地测出以下曲线: 但是在执行blkdiscard标记所有block为垃圾之后等待一会儿再测试,写入速度会翻倍到接近30M/s后快速再次掉速到10M/s左右: 由此猜测,该卡的主控在接收到命令后比较被动,并没有在后台进行活跃的垃圾回收,而是只回收了少部分的块。确实应了另一位老哥的话,好F配烂主控,鲜花插在牛粪上。 我又换了一张闪迪的Ultra 80M/s银卡,在没有discard之前做100个采样点的读写速度测试: 可以看出读取速度非常稳定,但是写入速度波动极大,完全无法稳定保证达到标称的U1速度。在个别测速样本中甚至速度低到接近0了,猜测是触发了现场擦写和垃圾回收导致失去响应。 同样使用blkdiscard命令通知SD卡所有数据块都是垃圾,并且等待大约3分钟之后再次执行同样的100个采样的读写速度测试: 非常巨大的变化!前一半采样点的写入速度基本上稳定在最高值,后半的曲线即使掉速也没有再掉到20M/S以下,可以推测闪迪的这张卡在接受到指令之后是在后台进行了垃圾回收的。 所以我们可以得出一些简单经验: 1. SD卡是支持trim的,但是受主控影响很大,不同的主控对trim指令的处理方式不同,可能是被动也可能是更激进的,也有可能便宜杂牌卡直接无视trim指令? 2. 对SD卡进行trim应该对恢复卡的掉速和延长卡的寿命有很大作用,避免已删除文件无法被垃圾回收导致磨损平衡失效。 由于另一位老哥的贡献,现在很多工业SD卡都可以读取寿命甚至是块擦写信息了,所以可以和上文所述的指令结合起来做一些测试SD卡主控的磨损平衡策略的实验。 本文来源网络,免费传达知识,版权归原作者所有。如涉及作品版权问题,请联系我进行删除,谢谢。查看原文请点击阅读原文 |