前言
几年以前,我被派去厦门上门去分析一个用户的手机卡顿问题,该用户的手机经常莫名无响应,刷机,恢复出厂都没有用,经过一通分析,原来该用户从熟人店里买到了一张盗版的SD卡(这年头坑的就是朋友),该SD卡读写速度很慢,顺序读写只有20MB/s。那为什么SD卡的读写性能对手机性能影响那么大?当时我的知识水平,只能从对比测试中发现这个问题,然后更换SD卡解决了这个问题,但是无法从原理上解释这种现象。经过那么多年的学习积累,我现在终于可以解释这个问题。
一、什么叫存储设备
在电脑上,存储设备就是硬盘,一般有固态硬盘和普通机械硬盘,
在手机上,存储设备就是内部存储或者外置SD卡,有EMMC和UFS X.X等类型。
1.1 一个程序如何访问存储设备上的数据
三个重要硬件,CPU,内存,存储
三者的通信关系如下:
一个程序需要通过CPU->内存->存储设备,CPU是无法直接访问存储设备的。
1.2 三者执行速度做对比
可以很明显的看到存储的速度明显拖了CPU和内存的后腿,所以程序访问存储设备里的速度很大程度上取决于存储设备的读写速度。
有人说,怎么不把存储做的快了一点,你要知道越快的东西越贵。如果你有钱,也可以把存储都换成内存,假设1T的硬盘都换成内存,你算算需要多少钱,而且目前我们普通用户对电脑手机的性能要求,存储1毫秒响应时间足够了。
思考一个问题:存储那么慢,CPU那不是会闲,那不是浪费了吗?
答案:操作系统实现了多进程(Task),让每个进程轮流使用CPU,变相的对于单个进程来说,CPU的执行时间也就变长了。假设一个CPU,有100个进程轮流使用,那不就是变相的对于单个进程来说,CPU的执行时间不就是30纳秒了,这样子不就和内存,存储的速度匹配上了嘛。
1.3 测试存储性能的两个指标
随机读写性能
顺序读写性能
PS:通过跑分软件测试计算的速度是CPU,内存,存储设备同时作用的结果,对存储设备的速度有一定的参考意义,但是不能作为存储设备的绝对速度。
二、Android存储架构图
整个Android存储架构分为三个层
1.应用程序
2.Linux内核
3.硬件层
我们接下来从这三个方面来分析如何提升手机的存储性能。
三、硬件层
硬件层也就是块设备,例如SD卡,固态硬盘,机械硬盘,都是块设备,基本上增大块设备绝对读写速度只能通过硬件结构升级和驱动优化,硬件厂商提供存储设备硬件和驱动,对于我们OEM厂商来说,基本能优化的空间为零。前言中讲的用户问题,就是属于硬件层的问题,遇到这种问题,只能换硬件,也就是换SD卡。
手机常见的块设备速度对比
UFS 3.1 > UFS 3.0 > UFS 2.1 > EMMC
记住UFS数字越大,速度越快。
小米10的黑科技揭秘-WriteTurbo
最近小米10大肆宣传的WriteTurbo大概率属于供应商的优化,这个方案主要是增加顺序读写性能,基本原理就是在块设备内部加入一块高速缓冲区,这样子内存就是和高速缓冲区通信,提升顺序读写的响应速度。不管怎么吹,也比不过UFS 3.1。
四、Linux内核
Linux内核中主要分三层,VFS,FileSystem,Block Layer。
4.1 VFS
VFS是虚拟文件系统的缩写,属于linux内核的一个抽象层,我们能优化的机会不多,但是并不是完全没有,由于这块代码比较标准,一般也不建议去修改。想深入理解这块知识,可以看我的视频王小二图解Android【005】一切皆文件
4.2 FileSystem
FileSystem是文件系统,目前手机中常见的F2FS和EXT4,两者没有绝对的好坏,只是目前来看在相同的存储硬件下F2FS比EXT4随机读写速度更快,我们可以通过刷机修改我们存储的文件系统。
如何优化FileSystem,优化文件系统的基本思路
1.以内存换速度,提前合理的缓存可能即将打开的文件索引,文件系统发起IO请求到Block Layer的速度将会大大增快。
2.优化存储的结构,F2FS和EXT4文件系统会影响到存储设备中文件以及文件信息的存储位置,在不同场景下,两者有着不同的存储结构
文件系统的代码一般都是开源的,而且贡献者一般都是linux大神,优化的难度挺大,但是绝对有机会的。只是我现在的水平只能看看文件系统,没有达到能优化的能力
黑科技揭秘-F2FS文件浏览器
有厂商说我们是F2FS文件浏览器,比传统的文件浏览器快,其实只不过换了文件系统成F2FS,或者对F2FS有一定的代码优化。你的硬件跟不上,就算你的文件系统再牛逼也只能一定程度提升随机读写性能。打个比方:汽车1.5T再牛逼,也比不过2.0自然吸气,UFS 3.0怎么也比不过3.1。
4.3 Block Layer
Block Layer主要是串联各个块设备驱动和文件系统,例如电脑上可能存在多块硬盘,手机上可以外置一个SD卡。
IO调度算法
Block Layer最重要的就是IO调度算法,也是比较复杂,主要任务就是合并IO请求,重新排序IO请求,转发IO请求到块设备驱动,可以通过优化或者切换调用算法,提升IO请求的效率。
目前常见的IO调度算法是:CFQ,NOOP,Deadline
有关IO调度算法的介绍和测试手段参考下面这个链接
https://blog.51cto.com/scoke/490546
如何优化
通过调整不同进程的IO优先级,提升前台进程的IO调度的效率。
通过修改IO调度算法,提升某些场景下IO整体性能。
5、应用程序
作为App开发人员,基本无法去优化平台的存储性能,但是可以优化APP的代码,减少存储设备的访问,将经常访问的数据放到内存里来,减少数据库的交互。Android官方也是警告千万不要在主线程处理复杂的IO操作。
只要所有App都乖乖地减少对存储设备的访问,这样子IO负载就不会高,手机也就越流畅。
6、总结
其实我个人认为,现在手机硬件不断升级,一台好的手机不单单是CPU内存 ,一块好的存储设备也是非常重要的,如果说CPU决定了这台手机的上限,那么存储设备算是这台手机的下限。
作为工程师,我们要做的就是将一块好的存储设备优化到极致,将差的存储设备优化到正常使用,我目前正在这个方向上努力学习,努力进步中。
7、思考
想想你们日常写的代码中有哪些属于存储设备的读写,欢迎留言。
回复「 篮球的大肚子」进入技术群聊
回复「1024」获取1000G学习资料