TRIM:提升磁盘性能,缓解Android卡顿
TRIM:提升磁盘性能,缓解Android卡顿
Android设备在使用一段时间后往往会变得卡顿,这与磁盘碎片和写入放大问题密切相关。本文深入探讨了Android系统中磁盘碎片的产生机制,以及TRIM技术如何优化磁盘性能。通过详细的原理分析和实际测试数据,揭示了Android系统中TRIM技术的实现方式及其对系统性能的影响。
故事起因
针对“Android系统越用越卡的问题”,腾讯某产品团队希望在自身产品中进行优化,从而提升产品口碑。经过初步分析,认为造成这种现象可能是由于两个方面原因:内存和磁盘。
内存方面:为了保证应用可以快速被再次调起,Android在内存管理上采用进程保持在内存中的策略。随着应用增多,试图保持在内存中的进程也会增多,从而影响系统的流畅度。
磁盘方面:长期使用Android手机会产生大量磁盘碎片,而磁盘碎片会降低磁盘的读写性能,从而影响系统流畅度。
逐步分析
Step 0:磁盘与系统流畅度的关系
磁盘对系统流畅度的影响主要体现在数据读写速度上。对于系统流畅度影响最直接的就是CPU的执行效率,但如果内存、磁盘以及网络的读写速度跟不上CPU的执行效率,就会造成CPU在处理任务时需要花费时间等待数据,从而影响流畅度。
Step 1:弄清Android磁盘的读写机制
目前,Android手机大多采用NAND Flash架构的闪存卡来存储内容。NAND Flash的内部存储单位从小到大依次为:Page、Block、Plane、Die。其读写机制如下:
- 删除数据时,芯片将标记这些Page为闲置状态,但并不会立马执行擦除操作。
- 写入数据时,如果目前磁盘剩余空间充足,则由芯片指定Block后直接按Page为单位进行写入即可。
- 写入数据时,如果目前磁盘剩余空间不足,为了获得足够的空间,磁盘先将某块Block的内容读至缓存,然后再在该Block上进行擦除操作,最后将新内容与原先内容一起写入至该Block。
这种机制会导致“写入放大”问题,即为了存储少量数据却需要进行大量读写操作,从而影响性能。
Step 2:解决“写入放大”问题的技术——TRIM
TRIM是一条ATA指令,由操作系统发送给闪存主控制器,告诉它哪些数据占的地址是“无效”的。基于TRIM技术,目前常见有两种方案:
- discard选项:在挂载ext4分区时加上discard选项,此后操作系统在执行每一个磁盘操作时同时都会执行TRIM指令。
- fstrim命令:选择合适的时机对整个分区执行TRIM操作。
Step 3:TRIM在Android中的实现
Android通过系统服务IdleMaintenanceService来监控系统状态并决定何时触发TRIM。根据IdleMaintenanceService.java源码,可以绘制fstrim的触发示意图:
Step 4:分析闪存碎片及TRIM对磁盘I/O性能的影响
通过测试数据分析闪存碎片和TRIM对磁盘I/O性能的影响:
- 测试对象:LG Nexus 5 with cm-11-20140805-SNAPSHOT-M9-hammerhead
- 测试步骤:
- 重新刷机,使用Bonnie++测试SD卡目录的I/O性能;
- 模拟长期使用SD卡的过程(期间需要避免TRIM触发),使用Bonnie++测试SD卡目录的I/O性能;
- 主动触发TRIM,使用Bonnie++测试SD卡目录的I/O性能。
测试数据如下:
测试结论:
- 在TRIM无效的情况下,长期使用SD卡,磁盘写入速度会受到明显影响;
- TRIM对因闲置数据块造成的I/O性能下降有一定的恢复作用;
- 大量的读写操作对SD卡造成了一定量的不可恢复的损耗。
Step 5:FSTRIM系统自动触发测试
测试结果显示FSTRIM大多数情况会被自动触发,但也存在无法触发的情况。可能的原因是FSTRIM对电量的要求略高,所以一旦发生意外情况(如应用的PUSH消息)终止了计划FSTRIM的执行之后,很长时间之内都无法再满足FSTRIM的启动条件。
总结&思考
- 磁盘碎片(更准确的说法是SD卡中的闲置数据块)会严重影响磁盘的读写性能,可能会导致Android系统越用越卡,而Android系统的FSTRIM对此有恢复的作用;
- 经过实验分析,FSTRIM并不一定能够按期(每天一次)执行。可能导致这一问题的原因是IdleMaintenanceService对电量的要求过高(未充电状态下大于80%)。
优化建议:
- FSTRIM对电量的要求略高,如需提高其触发频率可以从降低触发条件中对电量的要求;
- 在必要的情况下,可以发送特定的Intent事件,使系统强制触发FSTRIM。