android内核文件系统,在内核级别优化 SquashFS(一直到 Android 9)

重要提示:4.14 版之前的 Android 内核均支持 SquashFS。此功能已从可用于 Android 10 的所有内核(android-4.9-q、android-4.14-q 和 android-4.19-q)中移除,并且不再提供。

SquashFS 是 Linux 的只读压缩文件系统。该文件系统设计为只读属性,因此适合在系统分区上使用。很多 Android 设备都可以通过对其系统分区使用此文件系统来获益,例如以下设备:存储容量小的设备,例如 Android Watch。

闪存速度缓慢的设备(压缩可减少块 I/O 的数量)。

遗憾的是,SquashFS 的性能落后于 ext4。

优化

为提高 SquashFS 的性能,已经实现下列优化。

减少内存使用量和 memcpy 调用次数

读取块(默认为 128K)时,SquashFS 会尝试抓取包含此块的所有页面。

如果某个页面是最新页面或已被锁定,SquashFS 会转而分配一个完整块,提交读取请求,然后将其内容复制到这些页面。

这种方法极其低效;经过一段时间后,页面缓存可能包含最新页面,即使相邻页面并非最新页面也是如此。

代码现在能够处理有孔(即缺少页面)的块,因而可以通过以下方式来提高性能:减少 memcpy 调用次数

减少内存分配

异步读取

SquashFS 仍使用已弃用的 ll_rw_block() 函数。使用这种方法存在两个问题:顾名思义,该函数会等待读取完成之后再返回结果。这是多余的,因为 .readpage() 已在页面锁定上等待。此外,我们需要一个异步机制来高效实现 .readpages()。

合并读取请求完全取决于 I/O 调度程序。

ll_rw_block() 只会为每个缓冲区创建一个请求。在应该合并的内容方面,SquashFS 包含的信息比 I/O 调度程序多。此外,合并请求意味着我们对 I/O 调度程序的依赖会有所减少。

因此,ll_rw_block() 函数已被 submit_bio() 替换。

Readpages(预提取)

SquashFS 不会实现 .readpages(),因此内核会反复调用 .readpage()。

由于我们的读取请求是异步请求,因此内核可以使用其异步预读机制真正地预提取页面。

优化未压缩块的读取操作

诸如 Android 之类的现代系统包含大量经过压缩的文件。因此,映像包含大量无法压缩的块。

SquashFS 使用相同的逻辑处理经过压缩的块和未压缩的块:当 SquashFS 需要读取一个页面时,它实际上读取的是一个完整块(默认为 128k)。虽然对于经过压缩的块,这是必需的;但对于未压缩的块,这只是在浪费资源。

现在,SquashFS 只读取预读算法建议的内容,而不会读取一个完整块。

这极大地提高了随机读取的性能。

代码

AOSP 中提供 SquashFS 代码优化:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值