操作系统

I/O优化

2019-09-30  本文已影响0人  修塔寻千里

I/O基本知识


整个I/O操作由应用程序、文件系统和磁盘共同完成,应用程序将I/O命令发送到文件系统,文件系统在合适的时机把I/O操作发送给磁盘。整个流程的瓶颈在于磁盘I/O,但有时文件系统为了降低磁盘对应用程序的影响,会采用各种方式进行优化,因为文件系统的性能变得十分重要。

1、文件系统

文件系统,简单来说既是存储和组织数据的方式。对于Android来说普遍采用的文件系统是Linux的常用的ext4文件系统,华为在EMUI5.0以后就使用F2FS取代ext4,谷歌也在最新的旗舰手机Pixel3使用了F2FS文件系统。F2FS文件系统在小文件随机读写方面比ext4更快,不足之处在于可靠性方面出现过一点问题,随着谷歌和华为的投入和使用,未来F2FS将成为Android的主流文件系统。
应用程序调用read()方法,系统会通过中断从用户空间进入内核处理流程,然后经过VFS(Virtual File System,虚拟文件系统)、具体文件系统、页缓存Page Cache。下面是Linux一个通用I/O架构模型


I/O架构模型

2、磁盘

磁盘指的就是系统的存储设备。当应用程序要read()的数据没有在页缓存中,这时候就需要真正想磁盘发起I/O请求,这个过程要先经过内核的通用模块层、I/O调度层、设备驱动层,最后才会交给具体的硬件设备处理。


Android I/O

闪存是手机常用的存储设备,Android手机前几年通常使用eMMC标准,近年来通常会使用性能更好的UFS2.0/2.1标准。

1、文件为什么会损坏:

一个文件的格式或者内容,如果没有按照应用程序写入时的结果都属于文件损坏。

2、I/O为什么会突然变慢:

I/O的性能评估

1、I/O性能指标

最核心的指标为吞吐量和IOPS。吞吐量是指单位时间的数据读取或写入峰值,IOPS指的是每秒可以读写的次数。

2、I/O测量

I/O的三种方式

1、标准I/O

应用程序平时用到的read/write操作都属于标准I/O,也就是缓存I/O(Buffered I/O)。其特点为:

2、直接I/O


直接I/O访问文件方式减少了一次数据拷贝和一些系统调用时间,很大程度上降低了CPU的使用率以及内存的占用。但是,直接I/O有时候也会对性能产生不良影响:

3、mmap

它是通过吧文件映射到进程的地址空间,带来的好处有:

多线程阻塞I/O和NIO

1、多线程阻塞I/O

文件读写受到I/O性能瓶颈的影响,在到达一定速度后整体性能就会受到明显影响,过多的线程反而导致应用整体性能明显下降。

2、NIO


非阻塞NIO将I/O以事件的方式通知,的确可以减少线程切换的开销。其缺点是导致应用程序实现变得更复杂。其实NIO最大作用不是减少读取文件的耗时,而是最大化提升应用整体的CPU利用率。在CPU繁忙地时候,我们可以将线程等待磁盘I/O的时间来做部分CPU操作。

I/O跟踪

1、Java Hook

出于稳定性的考虑,采用Java Hook的方案,通过动态代理的方式,在所有I/O相关方法前后加入插装代码,统计I/O操作相关信息。这个方法存在下列缺点:

2、Native Hook

Profilo使用PLT Hook方案,它的性能比GOT Hook要稍好些,不过GOT Hook的兼容性更好一些。

3、监控内容

线上监控

通过Native Hook方案可以采集到所有I/O相关的信息,对于I/O的线上监控,我们需要进一步抽象出规则,明确哪些情况可以定义为不良情况,需要上报到后台,进而推动开发去解决。


1、主线程I/O

有时候I/O的写入会突然放大,所以尽量不要在主线程上操作,线上也经常发现一些I/O操作明明数据量不大,但是最后还是出现ANR。如果将主线程的所有I/O都收集起来,数据量会非常大,所以可以加上“连续读写时间超过100毫秒”这样的条件,之所以连续读写,是因为不少情况这是打开了文件句柄,但不是一次读写完的。

2、读写Buffer过小

文件系统读写是以Block为单位的,对于磁盘是以Page为单位读写,如果我们的Buffer太小会导致对此无用的系统调用和内存拷贝,导致read/write次数增多,从而影响性能。Buffer的大小对文件的读写的耗时有非常大的影响,耗时减小主要得益于系统图调用于内存拷贝的优化,Buffer的大小一般推荐使用4KB以上。

3、重复读

如果频繁的读取某个文件,并且这个文件一直没有被写入跟新,我们可以通过缓存来提升性能,不过未来减少上报量,通常增加几个条件:

4、资源泄漏

资源泄漏是指打开资源包括文件、cursor等没有及时关闭,从而引起的泄漏。利用Android 框架中的StrictMode实现监控资源泄漏,StrictMode利用CloseGuard.java类在很多系统代码已经预制了埋点,我们可以增加更多的埋点,据图步骤如下:

I/O启动优化

上一篇 下一篇

猜你喜欢

热点阅读