Android 性能监控系列一(原理篇)

时间:2022-09-18 09:55:07

Android 性能监控系列一(原理篇)

欢迎关注微信公众号:BaronTalk,获取更多精彩好文!

一. 前言

性能问题是导致 App 用户流失的罪魁祸首之一,如果用户在使用我们 App 的时候遇到诸如页面卡顿、响应速度慢、发热严重、流量电量消耗大等问题的时候,很可能就会卸载掉我们的 App。而往往获取用户的成本是高昂的,因此因为性能问题导致用户流失的情况是我们要极力避免的,做不好这一点是我们开发人员的失职。

去年我们团队完成了整个项目架构方面的重构(有兴趣的同学可以参考我之前的文章安居客 Android 项目架构演进Android 模块化探索与实践),目前已经能够很好的支撑我们的业务,并对团队的开发效率也有了一定的提升、项目质量也有了大幅的进步。

但是项目上线后,到底有没有性能问题?用户体验到底怎么样?在用户的使用场景中到底会遇到哪些性能问题?我们项目的性能短板又在哪里?这些问题的答案我们都不得而知,因此开发一套完善的性能监控体系势在必行。我们团队在今年开始着手开发自己的性能监控组件 APM,希望通过它来采集线上性能数据,找到性能短板,针对性的优化用户体验。

APM 全称 Application Performance Management & Monitoring (应用性能管理/监控)

后面我会通过一系列的文章来介绍 APM 的原理、框架设计与实现等等。本篇就是这个系列的第一篇,主要从实现原理方面来介绍 APM。按照目前的计划,这个系列大致会从如下几个方面来展开:

  • 原理篇:主要介绍 APM 的实现原理;
  • 设计篇:介绍整个 APM 框架设计;
  • 实现篇-Gradle Plugin:介绍 Gradle 插件在 APM 项目中的应用,以及如何开发一个 Gradle Plugin;
  • 实现篇-Javassist/ASM:Javassist、ASM 等字节码操作库的介绍,以及如何使用它们在编译时插入代码来采集各项性能数据;
  • 实现篇-数据存储及上报:介绍 APM 框架的存储上报机制及实现过程;
  • 发布集成:最后会介绍如何将库发布到 jCenter() 以及如何在生产项目中集成。

这里要向大家交代一点是,之前的文章为了极力做到将复杂的问题用通俗易懂的方式解释清楚,又要面面俱到,往往篇幅过长;诸如之前写过的RxJava系列6(从微观角度解读RxJava源码)神兵利器Dagger2安居客 Android 项目架构演进Android 模块化探索与实践写给 Android 应用工程师的 Binder 原理剖析等文章,篇幅通常都在 8000~10000字以上,通篇阅读下来可能需要近半个小时的时间,不太符合当下碎片化阅读的需求;因此在后面的写作上会控制篇幅,尽量控制在 10 分钟以内的长度。

这也是我为什么会将 APM 作为一个系列来介绍的原因,同时这也能保证后面在介绍 APM 的时候能够深入到实现细节,避免泛泛而谈。

二. Android APM 的基本原理

市场上有很多商业化的 APM 平台,比如著名的 NewRelic,还有国内的 听云、OneAPM 等等。这些平台的工作流程基本都是一致的:

  1. 首先在客户端(Android、iOS、Web等)采集数据;
  2. 接着将采集到的数据整理上报到服务器;
  3. 服务器接收到数据后建模、存储、挖掘分析,让后将数据可视化,供用户使用。

如下图: Android 性能监控系列一(原理篇)

我们介绍的 Android APM 框架其实就是在 Android 平台上应用的一个数据采集上报 SDK。主要包含三大模块:

  1. 数据采集
  2. 数据存储
  3. 数据上报

其中数据采集是整个 APM 框架的核心。

数据采集我们可以通过手动埋点的方式,但这种方式工作量巨大、不灵活,而且无法覆盖到所有场景;因此只能通过自动化的方式来采集数据。在应用构建期间,通过修改字节码的方式来进行字节码插桩就是实现自动化的方案之一。

三. Android 打包流程及字节码插桩原理

在谈字节码插桩的原理之前,首先我们看看 Android 的打包流程,如下图: Android 性能监控系列一(原理篇)

从上面这张打包流程图我们可以看到,一个 App 的所有 class 文件,包括第三方的 class 文件都会经过 dex 的过程打包成一个或者多个 dex 文件。

这其中涉及到两个很关键的环节:

  1. javac:将 .java 格式的源代码文件编译成 class 文件;
  2. dex: 将 class 格式的文件打包汇总,组成一个或者多个 dex 文件。

我们想要对字节码进行修改,只需要在 javac 之后 dex 之前遍历所有的字节码文件,并按照一定的规则过滤修改就好了,这里便是字节码插桩的入口。

那么我们到底如何介入打包过程,在 class 转换为 dex 文件的时候实现对字节码的修改呢?

答案是 transform api

Android Gradle Plugin 1.5.0 及以上版本,Google 官方提供了 transform api 作为字节码插桩的入口。我们只需要实现一个自定义的 Gradle Plugin,然后在编译阶段去修改字节码文件。对于 Gradle Plugin 的具体实现后面的文章再做详细讲解。

四. 修改字节码

找到了插桩入口,接下来就要对字节码进行修改。对于字节码的修改,比较常用的框架有 Javassist 和 ASM。

  1. Javassist 是一个开源的分析、编辑和创建 Java 字节码的类库,它提供了源码级别的 API 以及字节码级别的 API,源码级别的 API,直接使用 Java 编码的形式,而不需要深入了解虚拟机指令,就能动态改变类的结构或者动态生成类。

  2. ASM 是一个 Java 字节码操控框架。它能被用来动态生成类或者增强既有类的功能。ASM 可以直接产生二进制 class 文件,也可以在类被加载入 Java 虚拟机之前动态改变类行为。

ASM 和 Javassit 相比,API 贴近底层,比较难使用,需要对 Java 字节码和虚拟机方面有一定程度的了解。ASM 的优点就在于性能上的优势,且更加灵活;Javassist 的实现中大量使用的反射,所以性能偏低。

简单的说就是 ASM 虽然难以使用,但是功能强大效率高。是很多无痕埋点、APM框架的首选方案。

ASM 的具体时候我们放到这个系列后面的文章介绍。

五. 总结

Android APM 的原理其实非常简单,用一句话总结就是:

依据打包原理,在 class 转换为 dex 的过程中,调用 gradle transform api 遍历 class 文件,借助 Javassist、ASM 等框架修改字节码,插入我们自己的代码实现性能数据的统计。

以上所有过程都是在编译期完成的。

其实 Android 上的无痕埋点也是同样的原理,区别只不过是我们 hook 的点不同,采集的数据不同,因此掌握了 APM 的实现原理同样可以实现无痕埋点系统。

原理很简单,难的是实现细节。比如如何插桩采集到页面帧率、流量、耗电量等等。这些具体细节我们放到后面一一介绍。至于为什么放到后面……因为很多东西自己没做过我也不知道啊……

Android 性能监控系列一(原理篇)的更多相关文章

  1. [Android 性能优化系列]内存之基础篇--Android怎样管理内存

    大家假设喜欢我的博客,请关注一下我的微博,请点击这里(http://weibo.com/kifile),谢谢 转载请标明出处(http://blog.csdn.net/kifile),再次感谢 原文地 ...

  2. [Android 性能优化系列]内存之提升篇--应用应该怎样管理内存

    大家假设喜欢我的博客,请关注一下我的微博,请点击这里(http://weibo.com/kifile),谢谢 转载请标明出处(http://blog.csdn.net/kifile),再次感谢 原文地 ...

  3. [Android 性能优化系列]降低你的界面布局层次结构的一部分

    大家假设喜欢我的博客,请关注一下我的微博,请点击这里(http://weibo.com/kifile),谢谢 转载请标明出处(http://blog.csdn.net/kifile),再次感谢 原文地 ...

  4. Android性能优化系列之App启动优化

    Android性能优化系列之布局优化 Android性能优化系列之内存优化 Android性能优化系列之apk瘦身 应用的启动速度缓慢是我们在开发过程中常常会遇到的问题,比方启动缓慢导致的黑屏.白屏问 ...

  5. Android性能优化系列之apk瘦身

    Android性能优化系列之布局优化 Android性能优化系列之内存优化 为什么APK要瘦身.APK越大,在下载安装过程中.他们耗费的流量会越多,安装等待时间也会越长:对于产品本身,意味着下载转化率 ...

  6. 【转】Android性能优化之布局优化篇

     转自:http://blog.csdn.net/feiduclear_up/article/details/46670433 Android性能优化之布局优化篇 分类: andorid 开发2015 ...

  7. Android性能监控

    Android性能监控 一.搭建Android性能测试环境,参见<Android性能测试之Monkey使用>中内容. 二.启动Android虚拟机,可以通过eclipse启动,也可以通过命 ...

  8. &lt&semi;JVM下篇:性能监控与调优篇&gt&semi;补充:使用OQL语言查询对象信息

    笔记来源:尚硅谷JVM全套教程,百万播放,全网巅峰(宋红康详解java虚拟机) 同步更新:https://gitee.com/vectorx/NOTE_JVM https://codechina.cs ...

  9. &lt&semi;JVM下篇:性能监控与调优篇&gt&semi;补充:浅堆深堆与内存泄露

    笔记来源:尚硅谷JVM全套教程,百万播放,全网巅峰(宋红康详解java虚拟机) 同步更新:https://gitee.com/vectorx/NOTE_JVM https://codechina.cs ...

随机推荐

  1. ubuntu用作开发办公平台的完美体验

    2016年6月3日 对于使用使用linux操作系统作为办公平台的新手来说很不适应,需要在多种方式中找到自己喜欢,适合自己的方式比较难.摸索了很久终于发现了一个适合我自己的使用方式了.这种方式也适合其他 ...

  2. python——操作Redis

    在使用django的websocket的时候,发现web请求和其他当前的django进程的内存是不共享的,猜测django的机制可能是每来一个web请求,就开启一个进程去与web进行交互,一次来达到利 ...

  3. 【python】any&lpar;&rpar;和all&lpar;&rpar;

    any(iterable) 版本:该函数适用于2.5以上版本,兼容python3版本. 说明:如果iterable的任一元素不为0.''.False,返回True. all(iterable) 说明: ...

  4. Android开发中这些小技巧

    http://blog.csdn.net/guxiao1201/article/details/40655661 http://blog.csdn.net/guxiao1201/article/det ...

  5. win8&period;1 64 安装用友T3&plus;sql2005-64步骤

    1. 环境:win8.1 64 专业版  4G内存  .net framwork 3.5 2.初始过程及所需软件 安装sql2008数据库,安装完T3发现并不支持此数据库,运行T3老是出现连接数据时的 ...

  6. ubuntu scp

    一.将本机文件复制到远程服务器上 scp -r /Users/Dreamover/Desktop/jsnone dreamover@localserver:/var/www/project/ /Use ...

  7. Html5中的本地存储

    Web Storage web storage页面存储是html5为数据存储在客户端提供的一项重要功能,由于web storage API能够区分会话数据与长期数据.因此,相应API也分为两种: se ...

  8. LVS集群之工作原理和调度算法(2)

      LVS的工作机制 LVS里Director本身不响应请求,只是接受转发请求到后方,Realservers才是后台真正响应请求. LVS 工作原理基本类似DNAT,又不完全相像,它是一种四层交换,默 ...

  9. hive升级遇到的几个小问题

    1.hiveserver2正常启动,但是beeline连不上服务. 我的服务是开在本机的,但是用主机名和127好像都不能访问服务了 jdbc:hive2://172.19.1.11:10000> ...

  10. 将ant Design本地化,可通过link以及script直接引入html中使用

    一直想着能本地化antd的,不用npm以及dva那么复杂的配置环境来开发,并且本地化以后对以后链接flask的模板渲染机制也能很好的结合.下面是具体的实现方法: 1.将react的相关链接引入: &l ...