【Android性能优化面试题】ANR 线上问题如何监控

ANR 线上问题如何监控(滴滴)

这道题想考察什么?

对性能监控以及优化的掌握

考察的知识点

性能优化、性能监控、ANR的设计等

考生如何回答

ANR 全称 Applicatipon No Response;Android 设计 ANR 的用意,是系统通过与之交互的组件(Activity,Service,Receiver,Provider)以及用户交互(InputEvent)进行超时监控,以判断应用进程(主线程)是否存在卡死或响应过慢的问题,通俗来说就是很多系统中看门狗(watchdog)的设计思想。这道题问的是ANR的线上监控,所以我们需要做到怎么在发生ANR时,能够执行自己的某段代码逻辑完成ANR发生时相关信息的采集。

应用层如何判定 ANR

Android M(6.0) 版本之后,应用侧无法直接通过监听 data/anr/trace 文件,监控是否发生 ANR,那么大家又有什么其它手段去判定 ANR 呢?下面我们简单介绍一下

Android 6.0 可以利用FileObserver监听data/anr/trace

站在应用侧角度来看,因为系统没有提供太友好的机制,去主动通知应用是否发生 ANR,而且很多信息更是对应用屏蔽了访问权限,但是对于三方 App 来说,也需要关注基本的用户体验,因此很多公司也进行了大量的探索,并给出了不同的解决思路,目前了解到的方案(思路)主要有下面 2 种:

1.主线程 watchdog 机制

核心思想是在应用层定期向主线程设置探测消息,并在异步设置超时监测,如在规定的时间内没有收到发送的探测消息状态更新,则判定可能发生 ANR,为什么是可能发生 ANR?因为还需要进一步从系统服务获取相关数据(下面会讲到如何获取),进一步判定是否真的发生 ANR。

2.监听 SIGNALQUIT 信号

该方案在很多公司有应用(腾讯Matrix、爱奇艺xCrash,友盟+ U-APM)。我们在上面提到了虚拟机是通过注册和监听 SIGNALQUIT 信号的方式执行请求的,而对于信号机制有了解的同学马上就可以猜到,我们也可以在应用层参考此方式注册相同信号去监听(就是那个可以进程通信的IPC机制:信号机制)。

 	/**
     * 1、让SIGQUIT能够被监听处理!
     */
    sigset_t set;
    //初始化信号集
    sigemptyset(&set);
    //把SIGQUIT 信号加入到信号集中
    sigaddset(&set, SIGQUIT);
    //确定SIGQUIT不被阻塞(屏蔽) , 单线程或者单进程下可以用sigprocmask
    if (0 != pthread_sigmask(SIG_UNBLOCK, &set, &xcc_signal_trace_oldset)) {
    
    
        __android_log_print(ANDROID_LOG_ERROR, "Lance", "取消SIGQUIT屏蔽失败!");
        return;
    }
    /**
     * 2、注册SIGQUIT 信号处理!
     */
    struct sigaction act;
    //初始化
    memset(&act, 0, sizeof(act));
    sigfillset(&act.sa_mask);
    //设置处理信号的函数
    act.sa_sigaction = sigquit;
    act.sa_flags = SA_RESTART | SA_SIGINFO;//被信号打断的系统调用自动重新发起+使用sa_sigaction,而不是sa_handler
    //注册信号处理
    if (0 != sigaction(SIGQUIT, &act, &xcc_signal_trace_oldact)) {
    
    
        __android_log_print(ANDROID_LOG_ERROR, "Lance", "注册信号处理失败!!!");
        pthread_sigmask(SIG_SETMASK, &xcc_signal_trace_oldset, NULL); //还原
        return;
    }
    __android_log_print(ANDROID_LOG_ERROR, "Lance", "注册成功!!!");

当接收到该信号时,过滤场景,确定是发生用户可感知的 ANR 之后,从 Java 层获取各线程堆栈,或通过反射方式获取到虚拟机内部 Dump 线程堆栈的接口,在内存映射的函数地址,强制调用该接口,并将数据重定向输出到本地。

该方案从思路上来说优于第一种方案,并且遵循系统信息获取方式,获取的线程信息及虚拟机信息更加全面,但缺点是对性能影响比较大,对于复杂的 App 来说,统计其耗时,部分场景一次 Dump 耗时可能要超过 10S。

应用层如何获取 ANR Info

上面提到无论是 Watchdog 还是监听信号的方式,都需要结论进一步过滤,以确保收集我们想要的 ANR 场景,因此需要利用系统提供的接口,进一步判定当前应用是否发生问题(ANR,Crash);

与此同时,除了需要获取进程中各线程状态之外,我们也需要知道系统乃至其他进程的一些状态,如系统 CPU,Mem,IO 负载,关键进程的 CPU 使用率等等,便于推测发生问题时系统环境是否正常;

获取信息相关接口类如下:ActivityManager#getProcessesInErrorState()

在这里插入图片描述

最后

我整理了一套Android面试题合集,除了以上面试题,还包含【Java 基础、集合、多线程、虚拟机、反射、泛型、并发编程、Android四大组件、异步任务和消息机制、UI绘制、性能调优、SDN、第三方框架、设计模式、Kotlin、计算机网络、系统启动流程、Dart、Flutter、算法和数据结构、NDK、H.264、H.265.音频编解码、FFmpeg、OpenMax、OpenCV、OpenGL ES
在这里插入图片描述

有需要的朋友可以扫描下方二维码,免费领取全部面试题+答案解析!!!

猜你喜欢

转载自blog.csdn.net/datian1234/article/details/134897802