性能优化(十一)-性能优化总结

412 阅读5分钟

1、性能优化总结

  • Mem(2种方案 手动GC[ mATRIX ] 阈值的处理【koom】)
  • FPS(Handler机制、Printer检测卡断问题,消息处理完多少时间)、idleHandler
  • 延迟操作 Handler.postDelayed(Runnable r,long time)
    Looper.myQueue().addIdleHandler(new Message.IdleHandler(){
    //queueIdle  返回true/false   返回true意味着延时操作生效。如果messagequeue为空的时候,就自动回调这个方法。这个可以拿来做FPS的监控?**为啥?**
    
})
  • so动态加载 Tinker的so的加载流程。把dex加载到数组的最前面。

    • Relinker UnsatisfiedlinkError(so没找到对象的库):主要原因是兼容性的问题。包so的剪裁 是由于国内的厂商魔改ROM改的是so加载的路径(3种)。Relinker最牛逼的地方就是解析so的2进制文件,获取so的依赖属性。
    • 小于 6.0的版本有个东西叫so的依赖,一个so的库可能依赖其它三个库,顺序不能颠倒,否则就崩溃。这个机制面试种可以说。So的依赖属性很关键,RElinker可以解决这个问题。循环加载lib,最后加载loadPath。重新link
    • 网络下载so到本体,要通过这个Relinker库加载到内核当中。
  • 面试简历当中。动态加载就要提到兼容性问题,然后要去讲用到ReLiner,模拟这个库写自己的逻辑。

  • 动态加载放到简历去

  • ELF动态链接库 so 二进制协议。

  • 性能优化+架构+业务逻辑复杂度

  • 迅速接入到核心团队,架构,工程优化。不要碰UI的。

  • 自己通过relinker库帮我进行加载。试试看。写到简历中

  • Matrix边改边做性能优化。

2、android rabbit-client 是什么?

android rabbit-client 是一个开源的 Android APM 框架,是一个面向开发者的性能监控工具 rabbit-client 可以帮助开发者快速定位应用性能问题,主要功能如下1:

  1. 应用测速:可以准确统计应用 Applicaiton 创建耗时、应用冷启动耗时和页面 inflate 耗时 & 完全渲染耗时。
  2. FPS 分析:可以实时显示 FPS 并支持分页面分析 FPS。
  3. 慢函数检测:可以对代码中定义的敏感函数(比如耗时函数)进行检测,提供阈值报警等功能。
  4. 内存分析:提供内存泄漏检测、内存分析等功能。
  5. 网络分析:提供网络请求分析、网络延迟分析等功能。
  6. 崩溃分析:提供崩溃日志收集、崩溃原因分析等功能。

3、 性能优化总结

github.com/SusionSuc/r… github.com/Tencent/mat…

  • 设计还有架构 主流的开源项目 调用 怎么用?面试一定会问你。

  • Matrix:功能很全、相对比较重力度,不适合公司的业务的迭代,包体积很大。做到线上很鸡肋。经常crash。不能用于 线上,不能用于自己公司线上搭建

  • 听云sdk(>8.0 CPU指标问题)

  • 网易 腾讯GT

  • 360的APM gradle集成的时候会有很多的问题

  • httpdns可以作为一个亮点

4、指标的问题

  • 稳定性的问题(崩溃的问题) (bugly+breakpad+firebase(国外)) 一个set default 一个非set 非default?
  • 流量/网络 (Http协议的可达率、流量的大小)OkHttp的拦截器 全链路的监控APM、网络一体化的问题、协议本身(Socket)统一的处理 (这里不要谈)
  • 页面的FPS
  • 错误日志动态上传。压缩 加密 workmanager 约束(充电或者其它情况传) wakeup

5、建议大家重点关注的APM的性能指标:

  • 电量 最好讲battery historian、广播监听,统一的方案,
  • 流量消耗 打印出来 trafficStats/getUidRxBytes(int uid)/getTotalbytes() 后台流量偷跑怎么处理?后台起个定时任务,获取时间间隔流量,或者5s或者5min,计算平均值。
  • 内存指标的统计/内存的泄漏/
/**
     * 只能用在debug model,
     * */
    private fun getMemoryInfoInDebug(): RabbitMemoryInfo {
        val info = Debug.MemoryInfo()
        Debug.getMemoryInfo(info)

        val memInfo = RabbitMemoryInfo()
        memInfo.totalSize = (info.totalPss) * 1024 // 这个值比profiler中的total大一些
        memInfo.vmSize = (info.dalvikPss) * 1024   // 这个值比profiler中的 java 内存值小一些, Doesn't include other Dalvik overhead
        memInfo.nativeSize = info.nativePss * 1024
        memInfo.othersSize = info.otherPss * 1024 + info.totalSwappablePss * 1024
        memInfo.time = System.currentTimeMillis()
        memInfo.pageName = RabbitMonitor.getCurrentPage()

        return memInfo
    }
    
    
    //pss
     mActivityManager?.getProcessMemoryInfo(intArrayOf(Process.myPid())) ?: return 0
     
     //内存的泄漏  application的 生命周期的监听
    weakreference
    activity,activity.class.simplename
    activity onStop的时候 手动GC 2次 sleep  
  • 线上收集,需要有开关开启,当有重大问题的时候才收集。
  • 线下用leakcanary就可以了
  • application的生命周期的监听
  • weakreference。activity activity.class.simplename、activity onStop的时候 手动gc2次,给一个 sleep。申请大对象。

image.png

6、FPS

  • 原理知道 了 代码写在哪里?
 Choreographer.getInstance().postFrameCallback(new Choreographer.FrameCallback() {
    @Override    
    public void doFrame(long frameTimeNanos) {
        if(frameTimeNanos - mLastFrameNanos > 100) {
            ...
        }
        mLastFrameNanos = frameTimeNanos;
        Choreographer.getInstance().postFrameCallback(this);
    }
});
//推荐下面
public static void loop() {
    ...
    for (;;) {
        ...
        // This must be in a local variable, in case a UI event sets the logger
        Printer logging = me.mLogging;
        if (logging != null) {
            logging.println(">>>>> Dispatching to " + msg.target + " " +
                    msg.callback + ": " + msg.what);
        }
        msg.target.dispatchMessage(msg);
        if (logging != null) {
            logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
        }
        ...
    }
}

image.png

  • onActivtyResumed()开启监听 onWindowFocusChanged 如果界面可见我们可以收集pause暂停我们就停止。
  • 面试中说的点
    • 1、消息机制looper

    • 2、Choreographer。性能不太好。

    • 建议大家用message的消息监听,不要用这个编舞者。因为doframe不停执行,不需要刷新时也是不停执行,重复监听,不断去调用,对于线上监控性能不太好。

  • 推荐这种方案。

image.png

  • 丢帧不一定卡,卡顿一定丢帧。 Matrix中对卡顿有有定义,先掌握方法后面看代码就快了。

image.png

image.png

image.png

7、启动耗时监控

冷启动:App耗时时间检测 暖启动: activity的首帧判断 onWindowsFocusChange CP大法 ContentProvider中记录时间,再在first frame中计算,算下耗时。