




下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
先行版必看说明!先行版必看说明!/mobileperfman/BookResource/issues,创建issue。给我们宝贵的意见,让我谁适合读此书谁适合读此书致谢致谢 avin专家,Emi,,的鼎力支持先行版必看说明 谁适合读此 致 欢迎你离开桌面的世 故事的起 如何利用 资源类性 CPU 原理 工具 案例:音乐放的卡顿问 磁盘 原理 工具 案例:手Q启动过程中/proc/cpuinfo由10次的读操作降到2 案例:ObjectOutputStream的4000多次的写操 案例:手Q“健康中心”使用的Buffer过 案例:手Q解压文件使用Buffer太 案例:主线程有DB操 案例表刚创建完,就做大量的查询操作。.. 案例重复打开数据 网络 工具 案例:数据上报与流量的取 案例:WebView缓存使用的 案例:离线包重复案 案例:使用压缩策略优化资源流 案例:手Q发图速度优 案例:手Q在弱网下PTT重复发 网络军 电池 原理 工具 案例:QQWIFI耗 案例:动画没有及时释 稳定 稳定性原 案例:反复的空指针问 案例 内存不足异常原因分 内存不足异常类型分 内存不足类异常的原因排查和解 内存不足之前,我们能做哪些事情... 工具 兼容 原理 工具 动态检查:云测 动态检查:众 静态检查 静态检查:卡帕莱(优测 欢欢迎你离开桌面的世界故事的起点故事的起点记得我从和MACQQ项目中解放出来,就开始接手Q,组建专项测试团队。那时有几个小伙越来越差,我们开始用更严厉的标准像守护者一样守护QQ,例如:安装包的大小,接手后的超过则需求都不让合进来,从此安装包也刹住了车。但KPI这东西真的很厉害,像是洪水,不泄呢?为什么不能占用的内存?我提供服务,为什么不能消耗流量?为什么?能再变大了。这里需要,运营同学找到了应用宝的数据,发现有不少用户是3G,还有失败率的影响。数据跟汇报过后,我们拍定了更严厉的标准:0增长。类似的这些故事,解决专项BUG,有跟产品经理PK需求与专项性能的平衡。但是知道故事的人并不多,知道“为什面会介绍工具原理但更重要 是是一个个真实的案例BUG解决方案。如何利用我如何利用我资源类资源类性能CPU原理篇I/O密集型问题,另外一种就是现在要介绍具发现。但是,难道这章就没有东西可以说了?当然不是。我们就先从CPU作为硬件讲起。现在的CPU有非常多款,比较有名气的有MTK系列的,m系列的,三星的猎户座,的CPUV4倍。另外就是核心数,根据统计数据估算,现在主流的数依然是4核,起码有60%以上的用户量,8核的而另外一个跟CPU非常有关的,就是CPU调度器的策略配置。如上图所示,现在的主流其实是Hotplug,interactive,ondemand,pegasusq。下面工具集里面有每个的策略的含义。这里重点要说的interactiive,分析卡顿的时候可以关注在hotplug工具集TOP命令大家应该是非常熟悉的了,依靠adbstop就可以简单地列出进程们的各种信息。缺点TOPTOP。下面举几个TOP的小例子:11.排除的进程信adbtp|ev0S只打印1次按CPU排序的TOP10的进程信息:adbstop-m10-scpu-n指定进程的CPU,内存等消耗,并设置刷新间隔:adbstop-d1|grepadbsps-p-t-P-x–cPROCPROCCUCat/proc/[pid字 内 pgrpofthe session ttytheprocess pgrpofthe task numberofminor numberofminorfaultswithchild's numberofmajorfaults numberofmajorfaultswith 用户态CPU消耗(usermodejiffies) CPU消耗(usermodejiffieswithcstimecstimeT 下的信息adbadb cat 按需调节cpu频率,不操作的时候控制在最低频率,滑屏或进入应用后会迅速提升至最平。是一种在电池和性能之间趋向平衡的默认模式,但是对于智能来说,ondemand在性CPU运行在配置的频率范围内,配置中的用户自己添加的省电设置。当低需求时逐渐降低频率,相比ondemand费电很好,CP本身不需要资源去调整频率,但是电量消耗较快,温度也高些。源自三星猎户座处理器的一个调速器,可以单独调控单个CPU内核,理论上性能不错也很省电。DUMPSYS通过执行adb SYSTRACE&TRACEVIEW&CPU相关。SYSTRACETRACEVIEW作为定位工具,在交互类性能的工具里面已经说过了。而TREN会作为耗电的分工具在后面再重点介绍案例:音乐 的卡顿问问题类型:CPU消耗过高CPUQQ音乐在小米3上锁屏时会出现概率性断断续续,但亮屏时是不卡的具体细节:优化效果磁盘篇磁盘篇原理篇/O统I/O的调度策略等。磁盘硬件结构目前上使用大多为NANDFlash,NANDFlash架构是由东芝在1989年的,NANDFlash具有较快的抹写时间,而且每个单元的面积也较小,这让NANDFlash相较于NORNANDFlash的I/O接口并没有随机存取外部地址总线,它必须以区块性的方式进行,NAND由数个页(Page,多为4KB)所构成。为了延长驱动器的,其读写操作均是以“页”为单位进“写入放大”效应存空间上(已擦除状态)LBAFTL地址。此时,旧的地址内容在上述的无效区域进行再次写入的话,为了得到空闲空间,闪存必须先该“块”中所有的有效比如,现在写入一个4KB的数据,的情况就是,一个块里已经没有干间了,但是恰好4KB新时带来了原本只需要简单的写4KB的操作变成“闪存(512KB)→缓存改(4KB)→闪存擦除(512KB(WriteAplificaton)问题。1SD1M文件,统计文件写入耗时干净的数据块。这时再向SD卡写入1M的文件,统计文件写入耗时910090069300SD卡没有I/O调度策略有4种:cfq、deadline、noop和row,我们对目前市面上的339款 采样,有88.8%使用的是fcfq:I/ORT(reltim)、BEbesttry)、ILE(idle其中TBE又可8个子优先级。2.6.26I/O优先级的进程通常使用“none”作为调度I/O优先级会根据这些进程的CPUnice级别动态变更,io_priority=(cpu_nice+20)/5。操作。同时,noopFIFO的基础上还做了相邻I/O请求的合并。更全的I/O调度策略及对比,详见:/p/io-低磁盘空间的影响即在可用磁盘空间很少的情况下,APP的性能会有怎样的表现。这里作为磁盘专题,我们就来看看写入1M大小的文件,统计写入文件的耗时,一直到可用空间为5M为止。然后刚写入的文DEMO12款机型上测试,下图是写文件的耗时曲线图(横轴是磁盘可用空间,从左到右依从下表可以看出 MT7和OPPON5207的SD卡型号同为Toshiba032GE4,但是却有不同机B-199MT7-TL10OPPOvivoSM-GT-HMNOTEMI工具集 启动慢、滑动不流畅?开发在费了九牛二虎之力后,无奈地说没办法了,类的性能问题就随之解决了,用户的也就烟消云散,你又可以做着升职加薪的美梦了!资源类性能用户虽然不能直接感受到,如磁盘、cpu等,但是会直接影响交互类的体验。了这块的不足后,专项测试组最终自研了一款磁盘I/O的工具-I/OMonitor一、hookjavanative方法调调用系统IO方法变成调调调用java层回调函调调用系统原有对应的IO方调用jaa层回调函数aftrbeorehookedmehod获取此次IO操作的信2.1I/Oapp_process是Android中Java程序的,通过替换app_process,就可以控制,在任何一个应用中运行我们的代码。替换后的app_process工作流程如下:调用启动调用启动YlibforkoLD在UNIX的动 库的世界中,LD_PREOAD就是这样一个环境变量它可以影响程序的运行时 ,zygoteLD_PRELOADzygote的所有子进程都会继承这个环境变用我实现的fork函数,fork函数的流程如下:调用fork调用forkJavaVMYTENXPlatform.jar添加到环境变量
dexCLASSPATH中(XPlatform实现方法不同,但效果相同dex可以直importdexCLASSPATHDexClassLoader类来使用另一个jar包中的类,这样使用起来很麻烦,并且会有很大的限制。在XPlatform中主要hook了两个java方法,来system_server进程和应用进程的启动,并在这创建的任何一个应用进程和system_server进程也是生效的。N在Y这样就实现了在应用进程启动时控制在指定进程中运行OMonitor本,这样就可以实现指定场景的I/O信息收集,使做到更精准。运行python运行python控通过adb来运行运机上的运行Xplatform.jar的类导能,下面就来介绍I/OMonitor是如何使用的。hookI/OMonitor是用python写的控制,用来控制I/OMonitor的开始和停止。3,待安装完成后,把“/dt/dataom.xptformistller/co dl.xml”文件pull到电脑<moduledexname="common.jar"<moduledexname="common.jar"5,修改完成后,需要把module.xml文件push到“ ifname=="mainMonitorifname=="mainMonitor=IOMonitor('com.tencent.mobileqq')print"press'y'to7,运行runIOMonitor.py->操作APP->停止I/OMonitor,就可以获取到整个操作过程中,APP进行的I/O数据,I/OI/OMonitorcsvpullD盘下面,文件名为I/OI/O
从上图中可以看出,I/OMonitor获取到了相当多的数据,下面介绍一下各列数据的含义 操作该文件的线程名称readcount(writecount): publicvoidonCreate()if(DEVELOPER_MODE)}}性能分析 工具pagesizeI/O,而这些都是我们常规的优化数据库的。习惯从分析业务特性、尝试优化策略、验证的正数据库I/O数据JavaHook技术,获取到了Java层的I/O操作数据,虽然的IO操作在lib.so进行,而lib.so属于Native层,但很自然地想到通过NativeHook的I/O数据。些了解,NativeHook主要有以下实现方式:Inline1,修改环境变量这种方式实现最简单,重写系统函数open、read、writeclose,将so库放进环境变量数。可以参考Android使用LD_PRELOAD进行HOOK。2,修改GOTSO外部函数的时候,在编译时会将外部函数的地址以Stub的形式存放在.GOT表中,加载时linker再进行重定位,即将真实的外部函数写到此stub中。HOOK的思路就是:替换.GOT表中的外部函数地址。而lib.so中的I/O操作是调用libc.so中系统函数进行,所以修改GOT表的HOOK方案是可行的。修改GOT表的方案们采用的是orbywang提供的HOOKDK。libqliteoopnclose函red/writesqlit的源码下来,自看了许久的源码,经过无数次的调试,终于定位到原因,提供了unixSetSystemCall函数,可以来修改系统调用。如果把这个方法注释掉,就可以HOOKreadwrite的方法。staticint3_vfs*pNotUsed, /*TheVFSpointer.Notused*/constchar /*Nameofsystemcalltooverride3_syscall_ptr /*Pointertonewsystemcallvalueunsignedintintrc=_NOTFOUND;if(zName==0/*IfnozNameisgiven,restoreallsystemcallstotheir**settingsandreturnrc=for(i=0;i<sizeof(aSyscall)/sizeof(aSyscall[0]);没啥卵用,日志不输出,文件不创建。一切能想到的都用了,实在是不知道里面动了什3,INLINEInlineHook开始InlineHok可以Hook 库的内部函数,我们首先想到的是H klib .so内部I/O接口posixOpen、sekandrad、seekandwte以及robust_close。但是成功的 总是充满波折, 竟然将大部分的关键函数定义为tatic函数,如posixOpen 在c语言,sati函数是不导出符号的,而InlineHook就是要在符号表中找到对应的函数位置这样一来通过ooksqle内部函数的staticintposixOpen(constchar*zFile,intflags,intmode){returnopen(zFile,flags,mode);}既然这样不行,那我们只能更地Hooklibc.so中的open、read、write和close方法。因为不管种方法在自己编译的lib.so里面证实是可行的。几乎是的。为什么编译的lib.so库可以,用上的就不行呢?调用系统函数pread、pread64以及read来进行读文件。莫非编的so和里面的so的编译staticintseekAndRead(unixFile*id,3_int64offset,void*pBuf,intcnt){intgot;intprior=i64newOffset;#ifgot=osPread(id->h,pBuf,cnt,offset);SimulateIOError(got=-1);#elifgot=osPread64(id->h,pBuf,cnt,offset);SimulateIOEror(got -1);newOffset=lseek(id->h,offset,SEEK_SET);SimulateIOError(newOffset--);HOOK应用层SQL操作Hook应用代码其实就是HookDatabase里面的数据库增删改查操作,java层hook我们有一套Q启动过程中/PROC/CPUINFO10次的读操作降到2是同一个方法调用的,所以可以在isSupportGAudio()方法中,将的信息保存起来,下次再调用时,就不用再去文件中了。些信息了,优化后,该文件的读操作有10次降为2次避免重复打开关闭文件就是很有效的,即要避免重复读写。从上文得知I/O信息中的每一行数十有是可以优化的。使用缓存,对于需要多次的数据,在第一次取出数据时,将数据放到案例:对于系统API,只知其一造成重复写入Android系统中使用SharedPreferences文件来保存数据非常方便,在需要保存数据的地方调用关闭,从而造成commit()方法的随意调用,导致文件的重复打开和关闭。Android .qzone.xml文.qzone.xmlTT案例:手Q启动将 .MYCARRIER文件的写操作由主线 到QQ_FILE_RW线程I/O众所周知,Android的UI操作在主线程进行操作,主线程耗时越少,UI界面的生成就可以更OBJECTOUTPUTSTREAM4000多次的写操作1KObjectOutputStream()4000+次造成了很大的性能影响。存区中,然后再写到磁盘上。:找寻序列化最佳的实践I/OKB1000多次,频繁的写入势必严重影响APP性能。解决方法:可以通过使用缓冲区有效减少磁盘I/O46%36%I/OAPP来说,这个效果会更明I/O耗时11QBUFFER过小案例分析:从“健康中心”的I/O信息可以到,OfflineSecurity()方法了100多个文件,通过计Q解压文件使用BUFFER太小问题类型:问题类型:I/O 看到在该方法中使用Buffer大小确实只有2KB。经验,这里推荐使用的Buffer大小为8KB,这和java的默认的Buffer大小一致,Buffer大小至少应为4KB。当然,Buffer也不是越大越好,Buffer如果太大,会导致申请Buffer的时间变长,反而导致整体效率不高从上文看出I/OMonitor可以获取到读写的大小和次数 统API的次数所以读写大小/读写次数就可以得到Buffer的大小,如果uffer太小存在问题,则一:寻找解压和压缩的最佳实践AndroidZIPAndroid的有两种解压ZIP的方法,ZipFileZipInputStream带着以上问题,现在就开始ZIP的解压之旅。有些同学可能对理论分析不感,想知道结论1,ZIP文件结构ZIPFileEntry表示一个文件实体,存一个文件实体的偏移,文件最后由Endofcentraldirectory结束。04404426282224CRC-32442文件名称长度2扩展字段长度nmETNCEData增加一个Datadescriptor来记录。04CRC-3244CentralDirectoryFileENN04ENN044262822224CRC-32442文件名称长度2扩展字段长度2文件注释长度2244nmkEndofCentralDirectoryEN EN 字0404262822442Zip文件注释长度nQ1:CentralDirectory通过CentralDirectory获取ZIP信息,而不能通过扫描文件的方式,因为centraldirectory可能一些文件被删除或者已经更新。CentralDirectory中Entry的顺序可以和文件的实际顺序不一样。Q2:ZIPCZIPCentralDirectoryA和新文件C,这样就实现了删除文件B和更新文件C。2,ZIP文件解压ZipInputStreamreadZipF压缩文件 Yzlib解压出count字返返这里要重点介绍一下需要读入数据?N 解压入的数从流程图可以看jBffernave层。每次传入的数据大小是固定值为512字节,在InflaterInputStream.java中定义如下:staticfinalintBUFSIZE=对于压缩文件来说,最终会调用zlib中的inflate.c来解压文件,inflate.c通过状态机来对文件进 /4.4.4r1/xref/external/zlib/src/inflate.c,返回count字节并不等于buffer的大小,取决于inflate解压返回的数据。ZipFile通过RandomAccessFile随机zip文件,通过CentralDirectory得到zip中所有的面就可以利用RandomAccessFile的特性,每次读入的数据来提高解压效率。RandomAccessFile和InflateInputStream,通过getInputStream()返回,ZipFile的解压流程和ZipInputStream类似。protectedvoidfill()throwsIOExceptionif(nativeEndBufSize>0)ZipFile.RAFStreamis=(ZipFile.RAFStream)len=is.fill(inf,}elseif((len=in.read(buf))>0)inf.setInput(buf,0, 下面同样给出需要读入数据?nflater 据的大小传到native层nativebufferZipFile1KB64KB之间,如果文件大小介于二者之间,则可以一次将文件处理完。而对于ZipInputStream来说,每次能处理的数据只能是512个字节,所以ZipFile的解压3,ZIPFILEVSZIPINPUTSTREAM效率对比解压文件可以分三步:1,从磁盘读出zip文件2,inflate3,ZipFile在ative1KB~64KBZipInutream只有采用更大Buffer才可能达到ZiFil的性能。从上文可知,inflateinflate的解压算法有关,另一方面取nativeinfalte.cZipInputStream512字节数据到nativeZipFile每次传递的数据可以在1KB~64KBZipFile的解压效率更高。从javautilzipInflater.cppAndroiddemo验证(关键代码FileInputStreamFileInputStreamfis=newZipInputStreamzis=newZipInputStream(newBufferedInputStream(fis));byte[]buffer=newbyte[8192];FiledstFile=newFile(dir+"/"+ze.getName());FileOutputStreamfos=newFileOutputStream(dstFile);while((count=zis.read(buffer))!=-1){}}}ZipFilezipFileZipFilezipFile=newZipFile(files);InputStreamis=null;Enumeratione=zipFile.entries();while(e.hasMoreElements()){entry=(ZipEntry)e.nex is=dstFile=newFile(dir+"/"+entry.getName());fos=newFileOutputStream(dstFile);byte[]buffer=newwhile((count=is.read(buffer,0,buffer.length))!=-}}osizsiz100jpg低压缩率文高压缩率文read用次耗时read用次耗时ZipFile减少百分结论:1ZipFile的read39%~93%ZipFile的数据输出到BufferedOutputStream,等buffer满后再写入文件,这样做的弊端是,因为要凑满bufferread的调用次数增加,下面就对ZipFileZipInputstream做一个对比。FileInputStreamFileInputStreamfis=newZipInputStreamzis=newZipInputStream(newBufferedInputStreambis=newBufferedInputStream(zis)byte[]buffer=newbyte[8192];FiledstFile=newFile(dir+"/"+ze.getName());FileOutputStreamfos=newFileOutputStream(dstFile);while((count=bis.read(buffer))!=-1){}}ZipFileZipFilezipFile=newInputStreamis=null;Enumeratione=zipFile.entries();while(e.hasMoreElements()){entry=(ZipEntry) is=newBufferedInputStream(zipFile.getInputStream(entry));dstFile=newFile(dir+"/"+entry.getName());fos=newFileOutputStream(dstFile);byte[]buffer=newbyte[8192];while((count=is.read(buffer,0,buffer.length))!=-}}低压缩率高压缩率ZipFile耗时减buffer,增加了read的调用次数,导致整体耗时增加)Q4ZipFileZipInputStream且需全部解压出ZIP中的文件,如果你的场景符合以上两点,使用ZipFile无疑是正确的。同时,也可以利用ZipFile的随机能力,实现解压ZIP中间的某几个文件。1ZipputStream是顺序按流的方式文件,这种场景实现起来毫无压力。Directory会带来额外的耗时。ZipInputStream有15%~27%的提升。 顾一下ZipInputStream和ZipFile最高效的用法(红色为关键部分。ZipInputStreamzis=newZipInputStream(newBufferedInputStream(fis));BufferedInputStreambis=newBufferedInputStream(zis)byte[]buffer=newbyte[8192];1){}}while(e.hasMoreElements()){entry=(ZipEntry)e.nexement();if低压缩率文件,如文本isnewBufferedInputStream(zipFile.getInputStream(entry));elseif高压缩率文件,如is=ziFile.getnputStreamentrybyte[]buffer=new1){}案例:主线程有DB操作解决方案:将DB操作移动其他线程进行案例:表刚创建完,就做大量的查询操作。通过获取手Q首次启动的I/O数据,看到大量的对 字节。通过时间戳找到对应的SQL语句,其对应的是大量的SELECT*FROMExtensionInfoWHEREuin=?和SELECT*FROMFriendsWHEREuin=?语句,select语句耗时超过6秒。分 FriendsExtensionInfo在创建完之后,在插入好友信息前,需要先去表里面查询一下是否存在该记录。此时表是空的,所以才有大量的16字节的。案例:重复打开数据库竟然打开数据库424次,简直骇人听闻。多次打开数据库有什接就会被缓存,以供下次使用,只有当真正不需要时,调用close关闭即可。为什么要appplugindownloaddb80ms120ms每次打开I/O操作。gtWritableDatabas的注释也明确说明,该方法比较耗时,不能最后的话目前我们可以获取到SQL语句的堆栈和耗时,以及其对应的详细的磁盘I/O信息,我相信这对数据库优化来说有很大帮助。虽然我们也有些成果,但我相信应该还有可以做的事情,如果你有好的AUTOINCREMENT可没有你想的那么简单背景最近在分析手空(Android)60ms+,并且这条插1HOOKINSERTINTOevents(timestamp,content,status,send_count)VALUES(1445916309639,test,1索引惹的祸?createtableifnotexistsevents(event_idINTEGERPRIMARYKEYAUTOINCREMENTNOTNULL,contentTEXT,statusINTEGER,send_countINTEGER,timestampLONG)CREATEINDEXifnotexistsstatus_idxON3创建表的SQL4eventsINSERT耗时MTA(含索引MTA(不含索引AUTOINCREMENT-漏网之鱼INSERT耗时((INSERT1条INSERT1条INSERT50条AUTOINCRM到这里用过Qte的同学能会对这个结果觉得难置信OEMET关键字在里面好像很常用啊,大家用的时候似乎也没有担心效率问题。Q2:AUTOINCREMENTINTEGERPRIMARYKEY就是“主键”,我们先来了解一下主键。表的每行都有一个行号,行号用64位有符号的整形表示。支持使用默认的列名ROWID、_ROWID_和OID来行号。同时,如果表里某一列指定为INTEGERPRIMARYKEY类型,那么这一列和ROWID是等价的。也就是如果你指定某一列为主键,该列其实就是1开始,如果在插入数据时明确指定行号,则会将数据插入对号,就会出现_FULL错误,主键加了小结:AUTOINCREMENT的作用是保证主键是严格单调递增的。AUTOINCREMENT实现原理创建一个叫 _sequence的内部表来记录该表使用的最大的行号。如果指定使用AUTOINCREMENT来创建表,则 可能会修改site_sequence的内容因为 qlite_squene表带来的额外开销,将会导致INSERT 优化-逆向思维可好?里面绍的方法获取到两种情况下磁盘的读写数据。从中可以看出,AUTOINCREMENT会使写磁盘次数由2次增加到11次。这也能很好说明,因为要_sequence而增加额外的IO开销。5I/OAUTOINCREMENT的坑Q的现状?于主DB。6手QSQL7Q优化优化优化79Q总结以使用AUTOINCREMENT且不可,用在用该用的地方效果才更佳。网络篇网络篇一步推进,不妨把精力放在流量大带来的加载体验问题和服务器带宽成本问题上,这样会更容易驱动优化。尤其是流量带来的交互类性能问题,包括场景下带来的交互类性能问题,例如,这时,关于流量,从需求设计开始我们需要思考压缩,增量,不要忽略用户,而且成功的场景都比较。另外加上让产品痛的数据上报来说明问题,例如在复杂的WEBVIEW界面可以上工具集Q分业务流量统计实现用socket,有使用HTTP连接的,如果在应用层做流量统计,显然会异常复杂,手Q找到了一个巧1,流量统计上报模型流量数据队流量数 是否为N发发送消息到2,实现细节APPLICATION进行初始化系统SOCKETMonitorSocketImpl对象。MonitorSketImpl:tendsSockeIml通过反实例化出统的SocketImplgetInputStream()和getOutpuStream方法read方法,然后把的大小保存到MonitorSocketStat中。的write方法,然后把的大小保存到MonitorSocketStat中。整体流程覆写覆写轮询流量发送消息到
3,DEMO验证 logcatFIDDLER-HTTP协议测试Fiddler是一个HTTP协议调试工具,它能够记录并检查所有电脑和互联网之间的HTTP通信,查看所有“进出”Fiddler的数据(指、html、js、cssPC时代,Fiddler是前端调试和测试的利器,但是到了移动时代,Fiddler就被历史淘汰了吗?答案当然是否定的。Appwebview页面,webview的流量往往是很大的,因此发现其中的FIDDLER的工作原理Fiddler是在WinINetAPI和服务器之间做一个,通过定制这个的功能可以实现HTTP请求和前端调试的功能,这里我们主要用Fiddler来HTTP请求,从而找出其中的优化使用 是用Fiddle作为 跟电脑在一个局域网内可以用处于相同wifi下的笔记 的设置功能,打开WLAN并连到指定WiFiB,长按WiFi进入设置界面,选择“修改网络配置”C,在网络修改界面将设置为手动,同时输入主机名和服务器端口,这里的主机名为pc的IP地址,端为8888(Fiddler默认端)D,点击后,的设置就完成FiddlerToolsFiddlerOptions…ConnectionsAllowremotecomputerstoconnect,同时也在“HTTPS”页面通过设置是Fiddler支持HTTPS协议,完成后重新启动Fiddler。Transfo去除GZip、DEFLATETransfo去除GZip、DEFLATEHTTP流量优化优化HTTP的流量主要是减少Response的大小,可以使用的方法有:缓存和压缩缓存求时,就可以直接从缓存中资源,而不需要通过网络重新。1Pragma:no-2If-Modified-3If-None-Modified,客户端会使用缓存的response。上图中,HTTP的请求中缓存策略就设置为Pragma:no-cache,即不使用缓存,直接去服务器拉取新的ResponseControl控制Response如何在客户端缓存。Cache-Control可以标明Response如何以及如何使用,可以是如下选项Response可以在任何cache中,包括共享的Response将来不会被使must-和原始服务器确认Response是后,可以使用缓HTTP压缩CSS和JS可以通过压缩可以减少50%以上,所以对于文本资源推荐使用压缩后传输。式,如下图,该Response用的是gzip压缩方式。另外可以使用“Transformer”Response,可以看到压缩前后,Responsebody的大小,可以看到压缩前184KB,通过gzip压缩后,节省70%的流量。TCPDUMP-抓包的不二选是前提你得有对应的流量包,如何在上抓包呢?这时tcpdump就闪亮登场了,或许你对tcpdumpUnix系统,它可以将网络中传送not等逻辑语句来过滤掉无用信息。其在Windows下对应的版本成为WinDump,相信经常在Windows上抓包的同学一定不陌生。一、准备工作要想在上抓包你得先有一部才行(这不是废话吗?,Android和都tcpdumpAndoid为例进行介绍,其实这里的重点是你是要有root权限。或许你会说,如果我的rootAdroid是没办法获取root权限的,没关系,后面我们会介绍不需要rot权限的方法。 二、开始抓包之旅用的/data/local/tmp,完整的adb命令如下:adbpushtcpdump/data/local/tmpod777 tcpdump–w/data/local/tmp/tcp.pcap 5,把pcap拷贝到电脑上,就可以用wireshark按照我们之前介绍的方法来分析流量问题了。-c--i-r-s产生比vv更详细的输出.比如 ent时所使用的SBSE选项将会被打三、TCPDUMP高级应用cpdum最为有用的高级用法,可以利用它来匹配一些符合规则的数据包,便于后续分析,如果tcpdump中没有表达式,那么tcpdump会把网卡上的所有数据包输出,否则会将被expression匹配的包输出。srcdst,dstorsrcdstandsrc这些关键字指明了传输的方向。如果没有指明方向关键字,则缺省是srcordst关键字。ether、ip、arp、rarp、tcp、udp等类型。ether是匹配网卡,其他的几个关键字就是指明了的包的协议内容。如果没有指定任何协议,则tcpdump将会not、!and、&&or、||,这些关键字可以组合起WIRESHARK-流量分析wireshark,让你一跃成为wireshark高手。会成为你使用wireshark的门槛,因此这里不再介绍安装步骤。 抓包是通过tcpdump实现的,上文已经介绍过,这里我们 地介绍wireshark分析包的能力。过滤从上文中得知,我们在使用tcpdump抓包时,可以指定过滤条件,用来过滤指定的主机和协重任就交给wireshark了。协议过滤语法语法:Protocol.String1.String2ComparisonoperatorValueLogicalOperationsOther(string1string2是可选项http.request.methodPOSTor snmp||dns||icmp显示SNMP或DNS或ICMP封包 ip.addrip.addr==ip.src!=orip.dst!=ip.src/16显示来自10.230tcp.port25TCPtcp.dport=25TCPhttp.quest.method==PST"psthttphttp.host=="为httpT入”ip.”可以看到ip协议相关的过滤条件。内容过滤语法contains:Doestheprotocol,fieldorslicecontainatcpcontainshttp"payload中包含"http"tcptcp[20:3]47:45:54/*16进制形式,tcp20payload的前三个字节进行过滤*/过滤中函数的使用(upper、upper(string-field)-convertsastringfieldtouppercaselower(string-field)-convertsastringfieldtoupper(http.request.uri)contains过滤运算符EqualNotEqualne!=GreaterThangt小于LessTanlt<
GaterthanorEquatogeLessthanorEqualtoleLogicalANDandLogicalORorLogicalNOTnotcontains""bytes,不能用于原子字段,例IP地址,matchperl规则的正则表达式,对应协议或协议负载内的字符使用“FOLLOWTCPSTREAM”统计流量统计的方法,下面介绍一些wireshark中常用的流量统计功能。1“Summary”和“CommentsSummary”显示流量包的概要信息,包括数据包个数、数据包大小、抓包持续2,“Showaddressresolution”将IP地址解析为对应的3,“ProtoclHierarchy”按照TCP/IP4,onv tnList”将流量包中的连接划分不同类型连接的详二进阶篇IOIOGraphs是个强大牛的功能,可以配置出各种不同的图例。例如:利用bytes_in_flight+IOGraphs,就可以很方便对比大家的发包策略,Server的窗口策略。如图所示,配置filter分别为tcp.stream等于0,tcp.stream等于4,然后YAxis->Unit选择高级,之后就会有Calc可以填写,信则相对较少,这可以推断,手Q的接收窗口比 大,手Q在差网络下更容易遇到网络拥塞,当然也有可能是服务器回复ack的速度太慢导致。ack_rttIOGraphQRTT的时间比RTT略高,而在这种情Wireshark分析功能:Statistics->TCPStreamGraph->Time-SequenceGraph(Stevens)。利用Time-SequenceGraph很方便可以看出发包的方式,例如手Q会同一时刻发送许多包, 一个包等ACK回复。VOIP分析,今国外比较火的聊天软件)来举个例子,录制数据包TWiresharRTPT ehony->RTP,我们可以看到全部的Stream,因为存在发送和接收语音,而发送时没有经过网络的,因此我们先关注接收,也 是图三的数据,最大延时,最大抖动,平均抖动和丢 COMAEP利用sh,对齐两设备时间 Echo$1sshroot@$1dateY%m%ds$nowdate”sshroot@$1“date+%T–s 的差距(从发到接到的时间差:2090.072,另外,各种异常情况也在下面可以很方便的分析。使用命令行wireshark不仅有图形化的界面,还提供了完备令行解析方式,你可能会问:已经有图形化wireshark在wireshrk看分以实有有wireshark的的tshark命令行简单的介绍,参数参考文档。-r-r-r-RReadfil -R-z-z-z显示HTTP请求的模式以及状态-z务器名和-zHTTPIP地址IP地址和状态三扩展篇-流量自动化测试方案tcpdump+tshark来进行流量自动化测试的方案尽管很方并不完美的,在有些情况下是存在问题的,比如:当在抓包时并没有精确地过滤出待测APP的流量(做到这一点往往也是的,因为IP地址经常改变那么统计出来的流量就会包括其他APP或者服务的流量,造成不com.android.defcontainer的uid是10018。B、通过dAPP使的套接字通过/proc/net/tcp和/proc/net/tcp6APP在操作过程中使用的套接字,二者分别保存IPv4IPv6的套接字信息,如下图,uid10034的套接字信息是:IP地址A,端口tshark命令:tsharkraaa.pcapqzconv,tcp,得到如下结果,可以看到第一列就是会话的IP地址和端令行来做的自动化分析。PCAPHTP文件自动导出分析工具工具能力:自动导出Pcap中hp文 分析其中的重复资 工具原理pcaptcptcpsession。分析每一个Zip文件、gz文件:解压其中的文件至当前 session录的以及相应的session信息。工具用法分析,然后通过云分析的web页面查看结果,示例如下:Perflib在独立工具 gemonitor_box中调用云分析wgemonitor_box是一个可以独立运行的工具,通过命令行交互界面,获取用户的操作的开的url,然后展示给用户。工具地址用法,详见 PCAPHAR分析工具工具原理格式,基于JSON。Har目前是一种比较通用的数据格式。Har文件示例如下:{{"log":"veron":"2","creaor":{"browser":{},"pages":"entries":"comment":}}ResponseHeader等信息,然后按照规范,转换成通用har文件。等。har文件包含以下字段:–creator[object]HARbrowser[object,可选]–]–entriesarray]–HTTPcommentstring,可选](newin1.2)–内容就是一个HTTP请求的相应信息,信息格式如下:"entries":{"pageref":"time":50,"response":"timngs":{"servrIPAddess":"10.0"connection":52492,"comment":""}]request、respone、timingpagerefpages字段是否是4XX、5XX,是否开启了gzip压缩,请求相应时间是否超过限制等。工具用法分析,然后通过云分析的web页面查看结果,示例如下:Perflibjb运行完后通过httpwbpagemonitorboxwgemonitor_box是一个可以独立运行的工具,通过命令行交互界面,获取用户的操作的开始点以及结束点,并抓取相应的包Pcap包,然后提交云分析(调用接口的sdk使用的是Perflib中的,云分析结束后,打开分析结果的url,然后展示给用户。工具地址用法,详见 案例:数据上报与流量的取舍数据上报是指应用程序用户的某一行为的数据,并将统计数据上传到后端服务器的过程。上报验。数据上报对有志于提升用户体验的公司而言是经常使用的一种,对于腾讯这种追求用户体APP是耗费流量最多的,他肯定会以APP才导致还没到月末就没流量用了,又要他浪费银子去加流量了,久而久之,这会严重损害应用的体验和口碑。所以,对于移动端的APP来说,绝对不能数据上报,在每次使用手Q这样的超级APP使用的数据上报也是多如牛毛,我们也尽量保证对每次上报的数据在频率报告,这样可以及时发现问题手Q的质量。13KB左右,这里面可能就有问题了,于是就开始对该用例生成的pcap包和日志进行分析。11.5222.2612.0212.0912.0514.0912.7312.7214.0512.02,数据,是导致流量上升的主要原因,下面就把第6次的pcap包和日志拿出来进行分析。2wireshark分析pcapTCP12pcap包中有完整的建立和结束过程(TCP建立连接的三次”握手”和结束连接的三次“挥手3没有连接建立和结束的过程,即连接3在抓包之前就已经建立的。通过对连接1的IP地址分析,确认该IP指向的 upload.zip上(导出HTTP请求内容方法上文已讲过,和开发确认该连接为灯塔上报。2TCP数据包的传输音令字)报(连接1)和语音发送没关系,灯塔上报可能是流量存在异常的一个原因。1pcap分析第3-9次pcap包,统计以上三个连接耗费的流量语音发送发304050670890100平均7308689811自动化数据灯塔上报次数(次数1232灯塔上报导致流量增 msf的流量是 7月308月68月98月11ptt发送流 7月308月68月98月11msf手Q的每次灯塔上报都会有logcat日志输出,对应的关键字是RQD,通过查找日志,最终发现发送状态上报是为了上报该次语音是否发送成功,这为了保证语音发送的成功率,可以及时发现网络中出现的各种问题这个上报对实时性要求比较高,因此实时上报时必的。语音质量上报是为了掌握每次语音的发送质量,进而在语音质量方面提高用户体验,该上IMEI、版本号等大量的重复,如果用户每WEBVIEW缓存使用的坑策略,缓存的资源会在/data/data/packagedatabasecache两个文件夹,但是理想是费。当我们在打开手Q的大表情页面时,就抓到了开发类似的罪行,下面就看看我们是如何抓到2wiresharkpcap文件,统计整个过程消耗的流量,wireshark统计流量的方法有多面使用的流量为1.19M,手Q的“大表情”页面为webview页面,包含了大量的和文本信息,webview页面没有使用缓存,从而导致再次进入该页面时,资源通过网络又被重新方法1,查看磁盘 Android的weveiw的缓存策略会在/datadata/应用package下生成dabase与cache两个文件夹,database可以存放多个数据库文件,数据库中保存的是请求的url(手Q大表情”页面的缓存的url保存在webviwCooksChromiumrivatd 中,database中的数据库文件可以用Anroid的SDK 3.ee打开下图就是ebviewookiesCh db中的内容可以清晰地看到大表从导出的f_000089文件可以更直观地看出,大表情资源已在本地保存。cache文件 2fiddlerFiddler是一个http协议调试工具,它能够记录并检查电脑和互联网之间的http通讯,现在也可以用它来捕获上的http请求(操作步骤后文会介绍下图为fiddler的操作界面,左边为的HTTP请求的列表,右边为指定HTTP请求的详细信息,包括时间统计、请求内容等信息,这fiddlerB,点击“Caching”,如下图,可以得到该HTTP请求的头部中的Cache-Control为max- 秒,对应的是365天,从下面的解释可以得出,该资源的有效期为HTTPCache-Control进行简单的介绍,HTTPRequestCache-Control可以为no-cache、no-store、max-age、max-stale、min-fresh、no-transform、only-if-cached以及cache-extension,HTTPResponseCache-Controlpublic、private、no-cache、no-transform、must-响应和其对应的请求都不使用cache方法三:使用HARPageSpeedHARViewer中点击某cache-control为秒。cache中加载cache遍,这涉及到客户端发送HTTP请求时的缓存模式,客户端可以指定五种缓存模式,分别如下: LOAD_CACHE_NORMALAPIlevel17中已经废弃,APIlevel11LOAD_DEFAULTLOAD_NO_CACHE:不使用缓存,只从网络获取数据所以开发在这里就把缓存策略设置为LOAD_NO_CACHE,即所有的数据都只从网络上获取。最后,开发通过对不同进程的缓存做了(这也是为什么手Q的databases下有多个dbcache-control决定是否从网络上取数据,从而很好地解决了该问题,当前的代码如下:if(!enableCache){}案例:离线包重 载案发现过程以及影响pcap中的http文件比较md5值,发现部落的离线包存在重复的情况。同时通过观察大盘数据发现,每天资源使用量(直接线上资源)每天增加1百万~2百万,而离线资源使用量(使用离线包)每天减少1百万~2百万;:离线比从3:7变成了5:5,而且比例仍然在变问题定位以及解决方案手Q的离线包功能使用的是应用宝提供的一个jar包,这个jar包在离线包的时候会针对下载的url进行去重,不会针对同一个url多次,可以保证上层调用一次,只一次。了。经过排查发现上层确实调用了jar包进行了多次,但是为什么会多次调用?载用的jar于古老,不支持gzip解压,导致离线包无法使用。最终耗费了用户的流量,同时因案例:使用压缩策略优化资源流量Appwebw1Q打开这个页面是都会拉取大量的文本资源这些资源能压缩(资源也可以压缩,是可现场,有点像扫黄时使用的机,然后逐个webview界面都打开一下(也可以使用monkey配合获取了我们的pcap文件。下面我们使用了两个方法来定位问题:方法一:使用1Webview:androidweb2TcpdumpB 了足足503KB,这带来的效益是非常明显的。方法二:使用A,打开/,如下HAR”,即可保存对应的HAR文件A,打开http: /flint/index.php,这个可以为HAR文件生成对应的PageSpeed分数,如下除了文本可以压缩,当然也可以压缩。之前在手Q,我们就遇到过这个情况,使用tcpdump录制登录和登录后5分钟,使用刚刚提到的“方法一”,发现将近1M的流量,其中800多KB为PNG,而且大多数是没有alpha通道的。这时,使用jpeg压缩的优化效果是非常显著的,当时优化近30%的流量。显示。这时可以配合pyon获取文件的类型描述来更正的扩展名。importimportima=Image.opn(path)ifima.format==Q发图速度优化1,背景对于即时通信的APP来说,发送是最基础的功能,发送的快慢直接影响到用户体验,手Q为了提高的发送速度,和进行了发图速度的对比,不比不知道,一比才知道和之测试场景为:使用100KB的分别在3G网络和WiFi下,对二者进行发图速度的对比,测试 的耗时的3.5 的耗时的1.07 2,原因分析我们可以把的传输过程分为三部分,分别是客户端、传输链路以及服务器。传输链路对于我们来说是无法控制的我们只能从客户端和服务器来着优化客户端客户端有两个点可能影响到发图速度,(1)SendBuffer的大小,(2)户态向内核传输数据的wiresark的OGraph功能TCP ysisbytesinflight的关系,如下图所示window_sizebytes_in_flight滑动窗口说明接收端允许发送端发送的数据的大小,bytes_in_flight表示链路中确认的字节和服务器的处理能力,提高的发送速度。应用层在传输时,会将分成小片,调用send方法向内核传送分片,这里分片的8KB32KB,可以有效提高客户端的数据传输速率,调整后的window_size和bytes_in_flightwindow_sizebytes_in_flight非常接近,说明客户端已经充服务器我们知道服务器的RcvBuffer决定着滑动窗口的大小,因此可以增大RcvBffer来增加滑动窗口 RcvBuffer由3MS最大报文段)调整到10MSS,通过wireshark的Time-SequenceGraph可以看出,RcvBffer调整1MSS图13MSSTime-Sequence 图210MSSTime-Sequence3优化验证在完成以上优化后,又对手Q和 进行了发送速度的竞品对比,如下图所示,可以看出手Q的发图速率在WiFi环境下优于 发图速率(KB/秒手Q在弱网下PTT重复发送移动网络错综复杂,WiFi和G移动网络错综复杂,WiFi和G目前手Q遇到了这样的场景,用同样的发送PTT,手Q流量耗费是 么原因造成如此大的差距,下面就让我们一步一步地揭开的面纱。2案例分析2.1在3G网络下,用nexus5对比手Q和 发送20秒PTT的流量耗费,从看出,手Q流量为41KB,是 的将近2倍。场倍2.2结果分析1,从手Q日志看,原来nexus5在3G网络下,连接非常不稳定,PTT发送过程中出现连接中断,同时证实,在发送PTTQ的流量是的1Qlogcat数据。手Q在重连后,继续将剩余的8~18分片传完,后因在断网期间4-7个分片丢失,服务器要求图2服务器日原来手Q的PTT采用的是流式传输,即一边,一边进行传输,这样文件的传输过程采用的Q的传输协议在弱网下,针对重传机制设计的并不完善,导致在出现丢包的情况下,需要重传从丢失分片到当前文件的最后一个分片,造成了大量不必要的重2.3问题从上文得知,手Q的PTT发送采用的是流式传输,即边边发送,那么如果出现分片丢失,按照传输协议的逻辑,客户端需要传输从丢失分片到当前文件的最后一个分片。举例说明,如果当前到第8分片,这时服务器告诉客户端第4分片丢失,那么客户端只需传从丢失分片到结束,要注意,这里是结束而不是当前的文件,为什么会这样呢?当前分片去掉。这样就导致如果没有结束的话,除了当前正在录制的分片,仍会少传输一个分的分片,依次循环下去,一直到结束。造成的结果是:不管有没有结束,重传都会持续到2.4结论任何一个疏忽都有可能为用户造成损失网络军规WIFIAPP20KB接收富消耗<60K(富包括:,表情,语音,文件电池篇电池篇原理篇电功率。在电压恒定的前提下,我们只需要测量电流和时间就可以确定耗电。非充电状态下,的电能都是来自的电池。不妨从每台都会有power_profile.xml开始着手。PowerProfile,在厂家出ROM的时候,android是建议厂商通过下面介绍的PowerMonitor之类的工具来测试每个硬件模块的耗电情还有其实不属于硬件模块的和音频的耗电。下面我们来逐个介绍几个重要的硬件模块。硬件模块耗电分析TAndroid包含TAndroid包含AP和BP两个CPU,AP即Application 所有的用户界面以及app都是行在ap上的BP即asebandPrcesso 射频都是运行在这个CPU上的而一般我们说的耗电,PowerProfile里面的CPU,其实是AP。CPUBP5mA左右,但是因为唤醒,CPU(AP)就会运作,不同情况不一样,至少会导致20~30mA左右的耗电。另参考:Active就是开机之等sensor也会关闭,但这时系统其实依旧在运行状态。PowerManagerServer就会写“on”到/sys/power/state来执行lateresume的设Suspend:当系统刚进入EarlySuspend,而且wakelock已经都release了之而所谓唤醒就是让系统从S pen到Resmework或者Ac 或者是从arlyuspend到Active。怎样做到呢?主要靠alrmmanger和waklck做到。这里只介绍几个重点,AlarmManagerRTCELAPSED两种闹钟,前者是绝对时间,后者是相对时间,请不要搞是等到被其他原因唤醒了,他才触发闹钟。用的WakeLock还有一大堆。例如你应用间接调用mediaserver音乐的时候,也会起使用才能确保WIFI不会休眠。 /reference/android/app/AlarmManager.html另外一种耗电的情况就是CPU本身的高负荷。虽然大部分的POWER_PROFILE都不靠谱,但是我们姑且相信大厂的,如三星的。观察这些PowerProfile会发现一个规律,耗电在频率的时候,耗电会更加被放大。例如下图GT-i7100,CPU频率800是400的两倍,对应的耗电是1.5倍,但是电的一个主要原因,而不是简单的CPU运作就会很耗电。。。display按屏幕的材质分类,目前智能主流的屏幕可分为两大类,:一种是LCD(LiquidCrystalDisplay的简称OLED(OrganicLight-EmittingDiode的简称)即有机发系列屏幕则隶属OLED的范畴。其它的IPS、ASV、NOVA等并非屏幕材质,把它们称为屏幕显示技LCD屏幕本身是不发光的,白色光线由其背后的灯管发出,屏幕,照射到我们的眼睛,所以我们能够看OLED屏幕的显示机制与LCD不同,其屏幕的每一个像素是可以独立发光的。当显示全黑时,所有的像素都不发光,其效果相当于关屏(近似于LCD屏幕,且功耗更低。3G4G,WIFI,2G也会有类似的状态机概念。所以真正
C我们使用安卓SDK的C我们使用安卓SDK的API的reqetLocaonUpdate方法控制GPS的状态切换使用射 仪 的active状态;搜到很少 的active状GPS耗电与应用调用(requestLocationUpdate)更新GPS频率无关工具集下面介绍一系列的工具。实际上对于大部分的低级错误,这些工具都可以查出来。但是我们到现在位置,大部分的耗电成因还是产品需求,因此非常重要,而POWERMONITOR就是的工具,可以估算出的待机时间,并给予产品经理决策。 M移动设备工具TREPNPROFILER(以下简称TP)TP工作原理(如DS2780、MAX17048等)直接获取电流数据,可以理解成SnapDragon800+系列专门在如每个cpu、数字、电量等处buildin了多个sensors,当开始运行trepnprofiler时sensor说到这里有必要简单介绍下flugC 即电量计 ,因为 需要确定电池的可用电以及充电状态(SO,主要是根据剩余电量与电池容量的比来确定的,而 电池经过多次充放电导致电池容量变化,以及电压与电量之间不存在明确的关系。所以为了达到足够高的电量计量精度,引入了fulue,下图是现在使用比较广泛的 S2786(/en/app-notes/index.mvp/id/4224不过也基于依赖fuelgaugeIC获取数据的原因,电池类型不同肯定不同,不同也有可能不同,所以某些设备的数据并确,如已知以下几款(发现木有都是三星啊...SamsungGalaxySIII(SCH-SamsungGalaxyS4(SCH-SamsungGalaxySamsungGalaxyNoteSamsungGalaxyNote3(SM-DragonBoard(allInforceIFC6410 m测试确认数据无误的/ASUSNexusLGNexusLGNexusHTCOneSonyXperiaHTCDroidLGOptimusG软件用法ECLIPSE插件大家提到的一些问题,这次专门介绍一下这个TP的插件,让TP的使用更加得心应手。(TrepnPlug-inforEclipseGettingStarted)首先,安装TP插件需要:EclipsewiththeADTADBv1.0.31EclipseJuno setting100ms,以及下面数据完后用来过滤视图的,所以需要哪些数据,需要在这里设置,而非control面板上确认。之后就开始操作,完成之后点击停止,数据会自动记录到PC上,点打开文件的 是要停止之后才会传到PC,这时才能在charts里看到数据,所以开始后看不到数据不要惊慌。从官网安装(安装eclipse插件后,使用时也会自动在上安装 /mobile-development/increase-app-performance/trepn-A、右上角的在设置页面DATAPOINTS页面可以选 CPU,内存,GPS,屏幕等 的appC、选择Grap查看 的结果,StpPrflin停止 缺点 连接到PC之后处于充电状态,所以DEVELOPERTOOLSFORBATTERY版的android提供了一个工具,用于获取耗电量,adbs dumpsysbatterystats,这个工具可以获取各个app的wakelock、CPU时间占用等信息,同是增加了一个Estimatedpoweruse(mAh)功$adb$adbdumpsys Batterystats(batterystats)dump[--checkin][--history][--history-start][--unplugged][--charged][-c][--reset][--write][-h][<>]--checkin:formatoutputforacheckin--history:showonlyhistory--history-start<num>:showonlyhistorydatastartingatgiventime--unplugged:onlyoutputdatasincelast--charg
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 个人车位租赁合同集合15篇
- 国际赛事策划及组训培训资源
- 旅游智能安全行业市场调研报告:消费者需求与市场趋势分析
- 外地患者异地就医的透析指导
- 2025商场店铺租赁合同范本
- 中国银行兴安盟科尔沁右翼前旗2025秋招英文群面案例角色分析
- 中国银行佳木斯市抚远市2025秋招笔试金融学专练及答案
- 邮储银行甘孜藏族自治州九龙县2025秋招笔试思维策略题专练及答案
- 邮储银行中卫市中宁县2025秋招英文面试20问及高分答案
- 工商银行成都市蒲江县2025秋招笔试管理营销专练及答案
- 2025年CCAA服务认证基础考试试题(答案+解析)
- 2025年辅警招聘考试试题库附答案(能力提升)
- 搅拌车司机安全培训课件
- 2025年易制毒试题(含答案)
- 2025年医院药事管理自查报告及整改措施
- 工程地质学 第3版 课件 第3章 地质构造
- 2025标准建设银行贷款合同范本
- 2025年沥青搅拌站试题库(含答案)
- 2024北京一零一中高三10月月考语文试题及答案
- 个人成长与职业发展心理学
- 《思想道德与法治》(23版):绪论 担当复兴大任 成就时代新人
评论
0/150
提交评论