11讲io优化下如何监控线上操作_第1页
11讲io优化下如何监控线上操作_第2页
11讲io优化下如何监控线上操作_第3页
11讲io优化下如何监控线上操作_第4页
已阅读5页,还剩5页未读 继续免费阅读

付费下载

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、11讲IO优化(下):如何线上IO操作通过前的 习 相信你对I/O相关的基础知识有些认识也 解 测量I/O性能的法。但是在实际应中,你知道有哪些I/O操作是不合理的吗?应该如何发现代码中不合理的I/O操作呢?或者更进步,能否上持续应程序中I/O的使呢?今天就起来看看这些问题如何解决。I/O在I/O操作之前,你需要先知道应程序中究竟有哪些I/O操作。我在专栏前讲卡顿优化的中提到过,的Pro o为了拿到ftrace的信息,使了PLT Hook技术了“atrace marker fd”件的写。那么还有哪些法可以实现I/O,应该哪些信息呢?1. Java Hook出于兼容性的考虑,你可能第时间想到的法

2、就是插桩。但是插桩法样存在I/O操作。到所有的I/O操作,因为有量的系统代码也同出于稳定性的考虑,流程如下。退求其次还可以尝试使Java Hook案。以Andro d 6.0的源码为例,F eInputStream的整个调在L bcore.java中可以找到 挺不错的Hook点,那就是B ockGuardOs这个静态变量。如 可以快速找到合适的Hook点呢需要靠经验 但是耐查看和 析源码是必不可少的 作。java : FileInputStream - IoBridge.open - Libcore.os.open- BlockGuardOs.open -ix.open可 通过动态的式 在所有

3、I/O相关法前后加插桩代码 统计I/O操作相关的信息。事实上 B ockGua dO 还有些Socket相关的法,也可以来统计络相关的请求。看起来这个案好像挺不错的 但在实际使中很快就发现这个法有个缺点。性能极差。I/O操作调常频繁,因为使动态准。和Java的量字符串操作,导致性能较差,法达到线上使的标法Nat ve代码。例如中有量的I/O操作是在Nat ve代码中,使Java Hook案法到。兼容性差。Java Hook需要每个And o d版本去兼容 特别是And o d P增加对公开API限制。2. Native Hook如果Java Hook不能满需求,然就会考虑Nat ve Hook

4、案。Pro o使到是PLT Hook案,它的性能GOTHook要稍好些,不过GOT Hook的兼容性会更好些。关 种Nat ve Hook的实现式与差异 我在后会花篇幅专介绍选定Hook的标函数。天就不展开 。最终是从 bc o中的这个函数中因为使的是GOT Hook,需要选择些有调上个法的 brary。Matr x中选择的是libjavacore.so、libopenjdkjvm.so、libopenjdkjvm.so,可以覆盖到所有的Java层的I/O调,具体可以参考o cana y n cc。不过我更Pro o中atrace.cpp的做法,它直接遍历所有已经加载的 brary,并替换。o

5、pen(const char *pathname,flags, mode t mode); ssize t read(fd, void *buf, size t size);ssize t write(fd, const void *buf, size t size); write cuk close(fd);/ 动态对象Proxy.newProxyInstance(cix.getClassLoader(), getAllerfa(cix), this);beforeInvoke(method, args, throwable); result = method.invoke(mixOs, a

6、rgs); afterInvoke(method, args, result);public sic Os os = new BlockGuardOs(newix();/ 反射获得静态变量Class clibcore = Class.forName(libcore.io.Libcore); Field fos = clibcore.getDeclaredField(os);不同版本的Andro d系统实现有所不同,在Andro d 7.0之后,还需要替换下这三个法。3.内容在实现 /O后,需要进步思考需要哪些I/O信息。假设个件,希望知道这个件的名字、原始、打开件的堆栈、使了什么线程这些基本信

7、息。接着还希望得到这次操作共使了多时间,使的Buffer是多的。是次连续读完的,还是随机的。通过上Hook的四个接,可以很容易到这些信息。下是次I/O操作的基本信息,在主线个为600KB的“test.db”件。使了4KB的Buffer,连续150次,次性把整个件读完,整体的耗时是10ms。因为连读读写时间和打开件的总时间open64read chk write chkvoid hookLoadedLibs() auto& functionHooks = getFunctionHooks(); auto& seenLibs = getSeenLibs();:profilo:hooks:hookL

8、oadedLibs(functionHooks, seenLibs);相同可以判断出这次 ead()操作是 呵成的 中间没有间断。因为I/O操作真的常频繁,如此多的信息,对应程序的性能会造成多的影响呢?的耗时数据。是否使Nat ve Hook你可以看到采Nat ve Hook的法性能损耗基本可以忽略,这套案可以于线上。线上通过Nat ve Hook式可以分析。到所有的I/O相关的信息,但是到的信息常多,不可能把所有信息都上报到进对于I/O的线上决。,需要进步抽象出规则,明确哪些情况可以定义为不良情况,需要上报到,进推动开发去解1. 主线程I/O我不 次有时候I/O的写会突然放 即使是百KB的数

9、据 还是尽量不要在主线操作。上也会经常发现些I/O操作明明数据量不,但是最后还是ANR了。当然如果把所有的主线程I/O都收集上来,这个数据量会常,所以我会添加“连续读写时间超过100毫秒”这个条件。之所以使连续读写时间 是因为发现有不少案例是打开 件句柄 但不是 次读写完的。在上报问题到助分析问题。时,为了能更好地定位解决问题,我通常还会把CPU使率、其他线程的信息以及内存信息并上报,辅2. 读写Buffer过知道 对 件 统是以b ock为读写 对 磁盘是以page为读写 看起来即使在应程序上使很的Buffer,在底层应该差别不。那是不是这样呢?虽然后两次系统调的时间的确会少些,但是也会有定

10、的耗时。如果内存拷,导致read/wr te的次数增多,从影响了性能。的Buffer太,会导致多次的系统调和read(53, *., 1024) = 1024read(53, *., 1024) = 1024read(53, *., 1024) = 1024那应该选多的Buffer呢?样确定的。可以跟据件保存所挂载的录的b ock s ze来确认Buffer,数据库中的pages ze就是这所以最终选择的判断条件为:buffer s ze于b ock s ze,这般为4KB。read/wr te的次数超过定的阈值,例如5次,这主要是为了减少上报量。buffeze不应该 4KB 那它是不是越越好

11、呢 你可以通过下做 个简单的测试测试应的ote t件它的是40M。其中bs就是buffer s ze,bs分别使不同的值,然后观察耗时。通过上的数据致可以看出来,Buffer的对件读写的耗时有常的影响。耗时的减少主要得益于系统调与内存拷的优化,Buffer的般我使4KB以上。在实际应中,ObjectOutputStream和Z pOutputStream都是个常经典的例,ObjectOutputStream使的buffer s ze常。Z pOutputStream会稍微复杂些,如果件是Stored式的,它会使上层传的buffer s ze。如果件是Deater式的,它会使DeaterOutp

12、utStream的buffer s ze,这个默认是512Byte。你可以看到,如果使BufferInputStream或者ByteArrayOutputStream后整体性能会有常明显的。/ 每次测试之前需要动缓存echo 3 /proc/sys/vm/drop cachestime dd.sle.io/files/iotest of=/dev/null bs=4096new SFs(/data).getBlockSize()正如我上期所说的,准确评估磁盘真实的读写次数是较难的。磁盘也会有很多的策略,例如预读。它可能发超过你真正读的内容 预读在有量顺序会造成浪费。磁盘的时候 readahea

13、d可以幅提性能。但是量碎件的时候可能你可以通过下的这个件查看预读的,般是 28KB。可 利/proc/sys/vm/b ock dump或者 proc/d skss的信息统计真正的磁盘读写次数。般来说,3 重复读之前在块化改造的时候,因为模块间彻底解耦了,很多模块会分别去读些公共的配置件。有同学可能会说,重复读的时候数据都是从Page Cache中拿到,不会发真正的磁盘操作。但是它依然需要消耗系统调和内存拷的时间,且Page Cache的内存也很有可能被替换或者你也可以下这个命 模拟Page Cache的。如果频繁地某个件,并且这个件直没有被写更新,可以通过缓存来性能。不过为了减少上报量,我会

14、增加以下个条件:重复次数超过3次,并且的内容相同。期 件内容没有被更新 也就是没有发过wr te。加层内存cache是最直接有效的办法,较典型的场景是配置件等些数据模块的加载,如果没有内存cache,那么性能echo 3 /proc/sys/vm/drop caches/proc/diskss块设备名字|读请求次数|读请求扇区数|读请求耗时总和. dm-0 23525 0 1901752 45366 0 0 0 0 0 33160 57393dm-1 212077 0 6618604 430813 1123292 0 55006889 3373820 0 921023 3805823/sys/

15、block/disk/queue/read ahead kb影响就较 。4 资源泄漏在分析中,我有部分的OOM是由于件句柄泄漏导致。资源泄漏是指打开资源包括件、Cursor等没有及时c ose,从引起。这属于常低级的编码错误,但却常普遍存在。如何有效的经预置了埋点。资源泄漏?这我利了Andro d框架中的Str ctMode,Str ctMode利C oseGuard.java类在很多系统代码已到了这,接下来还是查看源码寻找可以利的Hook点。这个过程常简单,C oseGuard中的REPORTER对象就是个可以利的点。具体步骤如下:利反射 把C o eGua d中的ENABLED值设为t u

16、e。利动态,把REPORTER替换成定义的proxy。虽然在Andro d源码中,Str ctMode已经预埋了很多的资源埋点。不过肯定还有埋点是没有的,如Med aP ayer、程序的些资源模块。所以在程序中也写了个MyC oseGuard类,对希望增加的资源,可以动增加埋点代码。I/O与启动优化通过I/O,可以拿到整个启动过程所有I/O操作的详细信息列表。需要更加的苛刻地检查每处I/O调,检查清楚是否每处I/O调都是必不可少的,特别是wr te()。当然主线程I/O、读写Buffer、重复读以及资源泄漏是先需要解决的,特别是重复读,如cpu nfo、机内存这些信息都应该缓存起来。对于必不可

17、少的I/O操作,需要思考是否有其他式做进步的优化。对件使mmap或者NIO式。MappedByteBuffer就是Java NIO中的mmap封装,正如上期所说,对于件的频繁读写会有较的优化。安装包不压缩。对启动过程需要的件,包体积增。事实上Goog e P ay常希望可以指定在安装包中不压缩,这样也会加快启动速度,但带来的影响是安装不要去压缩 brary、resource、resource.arsc这些件,这样对启动的内存和速度都会有很帮助。且不压缩件带来只是安装包体积的增,对于户来说,Down oad s ze并没有增。Buffer复。耗。可以利Ok o开源库,它的ByteStr ng和B

18、uffer通过重等技巧,很程度上减少CPU和内存的消结构和算法的优化。是否可以通过算法或者数据结构的优化,让可以尽量的少I/O甚完全没有I/O。如些配置件从启动完全,改成时才对应的项;替换掉XML、JSON这些格式较冗余、性能较较差的数据结构,当public String readConfig() if (Cache != null) return cache;cache = read(configFile); return cache;然在接 来我还会对数据这块做的展开。2013年我在做Mu t dex优化的时候,发现代码中会先将c asses2.dex从APK件中解压出来,然后再压缩到c

19、asses2.z p件中。c asses2.dex做了次的解压和压缩,其实根本没有必要。那个时候通过研究ZIP格式的源码,我发现只要能构造出个符合ZIP格式的件,那就可以直接将c assses2.dex的压缩流搬到c asses2.z p中。整个过程没有任何次解压和压缩,这个技术也同样应到T nker的资源中。总结今天学习了如何在应层I/O的使情况,从实现上尝试了Java Hook和Nat ve Hook两种案,最终考虑到性能和兼容性 选择 Nat ve Hook案。对于Hook案的选择,在同等条件下我会优先选择Java Hook案。但论采哪种Hook案,码、分析调流程,从寻找可以利的地。都需要耐地查看源套案是只在动化测试,还是直接交给户线上使,这两者的要求是不同的,后者需要99.9%稳定性,还要具备不影响户体验的性能才可以上线。从到线上,需要量的灰度测试以及反复的优化迭代过程。课后练习的

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论