Android 系统性能优化(28)---Android 性能优化工具集合

磁盘

  1. 文件读写:每次打开、关闭或者读写文件,操作系统都需要经过从用户态转换为内核态的切换,这种状态的切换本身是很消耗性能的,所以为了提高文件的读写效率,就需要尽量减少用户态和内核态的切换。使用缓存可以避免重复读写,对于需要多次访问的数据,在第一次取出数据的时候,将数据放在缓存中,下次再访问的时候,就可以从缓存中取出来。
  2. Android手机里面的libsqlite.so调用系统的pread64pwrite64函数进行I/O操作
  3. 序列化ObjectOutputStream序列化磁盘的时候,会把内存中的每个对象保存到磁盘,在保存对象的时候,每一个数据成员会带来一次I/O操作。因此,在使用ObjectOutputStream的时候,在ObjectOutputStream上面再封装一个输出流ByteArrayOuputStream先将对象序列化后的信息写到缓存区中,然后再一次性地写到磁盘上。

    序列化磁盘读写方式优化前优化后
    序列化写磁盘ObjectOutputStreamBufferedOutputStream + ObjectOutputStream
      ByteArrayOutputStream + ObjectOutputStream
    序列化读磁盘ObjectInputStreamBufferedInputStream + ObjectInputStream
      ByteArrayInputStream + ObjectInputStream
    序列化磁盘读写方式优化前后I/O次数耗时(ms)
    序列化写磁盘优化前499162.8
     优化后187.3
    序列化读磁盘优化前719171.8
     优化后1109.9
  4. Buffer缓冲区大小:在读/写时使用缓冲区可以减少读写次数,从而减少了切换内核态的次数,提高读/写效率,根据实际经验,这里推荐使用的Buffer大小为8KB,这和Java默认的Buffer大小一致,Buffer大小至少应为4KB。当然,Buffer也不是越大越好,Buffer如果太大,会导致申请Buffer的时间边长,反而整体效率不高。可以采用文件大小除以读写次数得到Buffer的大小。这个方法由两个影响因子决定,一是Buffer size不能大于文件大小;二是Buffer size根据文件保存所挂载的目录的Block size来确定Buffer大小,而数据库的pagesize,就是这样确定的。
  5. SQLite:数据库在打开后,先不要关闭,在应用程序退出时再关闭。
  6. SQLite:在数据库中,应减少使用AUTOINCREMENT。AUTOINCREMENT可以保证主键的严格递增,但是使用AUTOINCREMENT会增加INSERT耗时1倍以上,所以使用AUTOINCREMENT不可以任性,用在该用的敌方效果才佳。

    SQLite官方:这个AUTOINCREMENT关键字会增加CPU,内存,磁盘空间和磁盘I/O的负担,所以尽量不要用,除非必须。其实通常情况下都不是必需的。

  7. Bitmap解码:
    (1)解码Bitmap不要使用decodeFile,因为在Android4.4以上系统效率不高。
    (2)解码Bitmap使用decodeStream,同时传入的文件流BufferedInputStream

    (3)decodeResource同样存在性能问题,请用decodeResourceStream
    解决方案: 
    1. 解码Bitmap要使用decodeStream,不要说使用decodeFile,同时传给decodeStream的文件流是BufferedInputStream
    2. decodeResource同样存在这个问题,建议使用decodeResourceStream

专项标准:磁盘

遵循标准标准优先级规则起源
避免主线程I/O避免主线程操作文件和数据库。P050%以上的卡顿问题都是由主线程I/O引起的。
 使用apply代替Sharepreference.commitP1apply是异步操作,commit是同步操作。
 提前初始化SharepreferenceP1在多进程和旧版本的Android中,初始化过程的I/O读/写都是在主线程的。
减少I/O读写量减少使用select *P1减少从数据库读取的数据量,减少耗时。
 利用缓存减少重复读写P2内存缓存命中率极高,投入产出高。
 数据库减少使用AUTOINCREMENTP1因为要多操作一个表,索引Insert耗时增加了2~4倍。
 使用合适的数据分页P0sqlite读写磁盘是以page为单位的,在3.12.0之前,sqlite默认page size是1KB,从3.12.0开始,page size调整为4KB。
 频繁查询表使用索引P0索引可以极大地较少读磁盘的数据量,极大地提升效率。
 避免无效索引P0无效索引的问题通常是严重的。除了触发全表扫描,产生大量的冗余的读/写之外,还降低了写入性能。
减少I/O操作次数使用8KB Buffer读/写P0可以减少2~3倍的耗时。
 批量更新数据库使用事务P0启用事务,根据业务规模,会大量减少I/O读写量和操作的次数,从而提升效率。
 ZIP压缩大量小文件的时候建议使用zipInputStreamP2 

内存

内存检测工具集

工具问题能力
top/procrank内存占用过大,内存泄露发现
meminfoNative内存泄露,是否存在Activity、ApplicationContext泄露、数据库缓存命中率低发现+初步定位
MAT、Finder、JHATJava层的重复内存、不合理图片解码、内存泄露等等发现 + 定位
libc_malloc_debug_leak.soNative内存泄露(JNI层)发现 + 定位
LeakCanaryActivity内存泄露自动发现 + 定位
StrictModeActivity内存泄露自动发现 + 初步定位
APT内存占用过大,内存泄露发现
GC Log from Logcat、GC Log生成图表人工触发GC for Explicit而导致的卡顿,Heap内存不足触发GC for Alloc而导致的卡顿发现 + 初步定位
SystraceGC导致的卡顿发现
Allocation Tracer申请内存次数过多和过大、辅助定位GC Log发现的问题发现 + 定位
chrome devtoolHS的内存问题发现 + 定位

  Android使用的是一个去掉了swap的linux内核(至少在Android4.4以前的版本都是这样的),这样就阻碍了Android上的应用程序使用Page out(应用程序使用的内存,对操作系统而言都是一张张的page,而对于老化的page,操作系统可以将它们从内存中置换到硬盘上,这种操作叫做page out),这一常规的内存操作。 
  Android框架对于进程内存的第二个管控特征是,每个进程都有一个内存最高阀值(纯净的Native内存申请不算在内),一旦进程申请内存突破了这个阀值,将会产生异常,并退出运行时的内存空间。简单的说,也就是Android为每个进程已经分好了一块蛋糕,至于你吃或者不吃,是你的自己的事情了。但这是否意味着Android应用程序为了效率考虑,应该玩命的申请内存,使自己的内存沿着天花板滑行,这样是否最健康呢?答案也不一定。 

  Android的第三个管控特征是,进程都有可能被杀。在物理内存吃紧的时候(通常在使用meminfo查看内存概况的PSS总值达到设备物理内存80%的时候),Android框架就开始根据一套自由的LRU进程Cache列表来杀死进程,被杀死的进程在死前将会得到通知,用以保存现场。而这部分被杀死的进程所腾出来的物理内存,就可以用于某些应用程序的内存申请需求。


  Android内存框架下的各种管控特征:

  • 没有Page out, 所以物理内存更加金贵。
  • 每个进程都有一个内存上限,所以蛋糕是已经被分配好的。
  • 所有的进程都有被杀的可能,所以要做好被杀准备。

专项标准:内存

遵循原则标准优先级规则起源
避免内存泄露避免Activity泄露P0大部分严重的内存泄露都是Activity泄露,因为这意味着被引用的View、图片等全部泄露。
减少常驻内存尽量使用RGB565P1手机QQ使用RGB565将节省部分图片的内存,高达50%。
 避免内存重复P1手机QQ去掉头像30%的重复缓存,提升缓存的命中率和流畅度。
 res/drawable里的图片,建议使用Drawable.createFromStream来加载P1使用错误的文件夹,导致图片被放大,最终APP使用的内存增加。
 将图片放置到合适的资源文件夹(hdpi、xxhdpi等)P1使用错误的文件夹,导致图片被放大,最终APP使用的内存增加。
减少GCBitmap尽量使用inBitmapP1可以减少GC,提升流畅度。
 建议使用SpraseMap或者ArrayMapP2 
 建议StringBuilder重用(如果由线程使用可配合ThreadLocal)P1手机QQ与QQ空间日志改造,利用delete来替代new,给予合理的初始化长度,写日志性能提升多倍。

网络

工具集

工具问题能力
Wireshark最专业的网络分析工具,全部网络性能问题的分析定位都可以查看它。发现+定位
Har+Pagespeed吧pcap转为har,上传到http://stevesouders.com/flint/发现+定位
fiddler主要针对HTTP,帮助发现HTTP众多性能问题,还能模拟错误和演示的HTTP返回发现+定位
tcpdump抓包工具,需要ROOT权限发现+定位
traceroute定位网络路由问题,包括就近接入、跨运营商问题发现+定位
ARO无压缩、重复下载、缓存失效等,还有雅虎军规中的其他问题自动发现+定位
WebP/BPG图片压缩方案,前者基于webm的帧内压缩,后者基于H.264的帧内压缩解决
SPDY/HTTP2.0/QUIC网络协议,利用FastTcpOpen减少握手次数,利用UDP更好的适应网络抖动解决
WebPageTest.org如果要做Web应用的数据上报,建议参考之。它提供了LoadTime、StartRender、SpeedIndex,DOM Elements等耗时发现+定位
tPackageCapture无ROOT转包定位
ATC最专业的弱网络模拟工具,除能模拟窄带、延时、丢包、损坏包外,最关键的还有包乱序的情况发现

工具库

工具说明
AndroidGodEyeAndroidGodEye是一个可以在PC浏览器中实时监控Android数据指标(比如性能指标,但是不局限于性能)的工具,你可以通过wifi/usb连接手机和pc,通过pc浏览器实时监控手机性能。

系统分为三部分:
1. Core 核心部分,提供所有模块;
2. Debug Monitor部分,提供Debug阶段开发者面板;
3. Toolbox 快速接入工具集,给开发者提供各种便捷接入的工具。

AndroidGodEye提供了多种监控模块,比如cpu、内存、卡顿、内存泄漏等等,并且提供了Debug阶段的Monitor看板实时展示这 些数据。而且提供了api供开发者在release阶段进行数据上报。



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值