美文网首页优化
腾讯性能检测库Matrix源码阅读

腾讯性能检测库Matrix源码阅读

作者: 普通的程序员 | 来源:发表于2019-04-15 16:27 被阅读44次

    目录

    • 0.前言
    • 1.初始化
    • 2.内存监控MemoryCanaryPlugin
    • 3.性能监控TracePlugin

    0.前面随便写点什么

    项目地址
    https://github.com/Tencent/matrix


    1.初始化

      Matrix.Builder builder = new Matrix.Builder(application);
     // build matrix
      builder.patchListener(new TestPluginListener(this)); 
    // add general pluginListener
      DynamicConfigImplDemo dynamicConfig = new DynamicConfigImplDemo();
     // dynamic config
      
      // init plugin 
      IOCanaryPlugin ioCanaryPlugin = new IOCanaryPlugin(new IOConfig.Builder()
                        .dynamicConfig(dynamicConfig)
                        .build());
      //add to matrix               
      builder.plugin(ioCanaryPlugin); 
      //init matrix
      Matrix.init(builder.build());
      // start plugin 
      ioCanaryPlugin.start();
    

    建造者模式,内部类Builder
    patchListener就是监听每一个patch的生命周期
    DynamicConfigImplDemo 实际是IDynamicConfig的实现类,用于动态设置参数,里面也有个matrix-config.xml是参数配置文件。

    Plugin后续再说。

    Matrix内部维护了一个HashSet

     public Builder plugin(Plugin plugin) {
                if (plugins == null) {
                    plugins = new HashSet<>();
                }
                String tag = plugin.getTag();
                for (Plugin exist : plugins) {
                    if (tag.equals(exist.getTag())) {
                        throw new RuntimeException(String.format("plugin with tag %s is already exist", tag));
                    }
                }
                plugins.add(plugin);
                return this;
            }
    

    先用tag做判断,再者HashSet也不允许有重复的值存在,也就是Matrix里同一类型的plugin只能有一个。

    接下来就是

    public Matrix build() {
                if (pluginListener == null) {
                    pluginListener = new DefaultPluginListener(application);
                }
                return new Matrix(application, pluginListener, plugins);
            }
    
    private Matrix(Application app, PluginListener listener, HashSet<Plugin> plugins) {
            this.application = app;
            this.pluginListener = listener;
            this.plugins = plugins;
            for (Plugin plugin : plugins) {
                plugin.init(application, pluginListener);
                pluginListener.onInit(plugin);
            }
        }
    
    public static Matrix init(Matrix matrix) {
            if (matrix == null) {
                throw new RuntimeException("Matrix init, Matrix should not be null.");
            }
            synchronized (Matrix.class) {
                if (sInstance == null) {
                    sInstance = matrix;
                } else {
                    MatrixLog.e(TAG, "Matrix instance is already set. this invoking will be ignored");
                }
            }
            return sInstance;
        }
    

    至此,完成了Matrix装饰类的初始化。

    其余的每一个Plugin插件初始化斗差不多,就用demo里的IOPlugin
    每一个Plugin像glide那样,传入一个动态参数。
    在Matrix的构造方法里,plugin依次调用init方法,plugin的init方法初始化PluginCore核心类,最终plugin的start方法也是core核心类的start方法。


    2.内存监控MemoryCanaryPlugin

    初始化多了一个HashSet维护的activity集合

    MemoryCanaryPlugin类
    public void init(Application app, PluginListener listener) {
            super.init(app, listener);
            mCore = new MemoryCanaryCore(this);
            HashSet<String> specialActivities = mMemoryConfig.getSpecialActivities();
            if (specialActivities != null) {
                for (String activity : specialActivities) {
                    mCore.addSpecial(activity);
                }
            }
        }
    
    MemoryConfig类
    public HashSet<String> getSpecialActivities() {
            String strActivities = mDynamicConfig.get(IDynamicConfig.ExptEnum.clicfg_matrix_memory_special_activities.name(), DEFAULT_SPECIAL_ACTIVITIES);
            if (strActivities == null || "".equals(strActivities)) {
                return null;
            }
    
            String[] vecActivities = strActivities.split(";");
            HashSet<String> result = new HashSet<>();
            for (String activity : vecActivities) {
                if ("".equals(activity)) {
                    continue;
                }
    
                result.add(activity);
            }
            return result;
        }
    

    重点关注MemoryCanaryCore类
    start方法首先检测机器条件是否允许,获取内存信息,注册生命周期回调callback----添加到set里进行管理,还有组件回调---在合适的时候dumpMem信息

    public void start() {
            mLevel = DeviceUtil.getLevel(mContext);
            if (!isApiLevelOk() || mLevel == DeviceUtil.LEVEL.LOW || mLevel == DeviceUtil.LEVEL.BAD || mLevel == DeviceUtil.LEVEL.UN_KNOW) {
                mIsOpen = false;
                return;
            }
    
            mIsOpen = true;
    
            //all in kb
            mTotalMemory = DeviceUtil.getTotalMemory(mContext) / 1024;
            mLowMemoryThreshold = DeviceUtil.getLowMemoryThresold(mContext) / 1024;
            mMemoryClass = DeviceUtil.getMemoryClass(mContext);
            if (mLowMemoryThreshold >= mTotalMemory || mLowMemoryThreshold == 0) {
                mIsOpen = false;
            }
    
            ((Application) mContext).registerActivityLifecycleCallbacks(mActivityLifecycleCallback);
            mContext.registerComponentCallbacks(mComponentCallback);
        }
    
    private final Application.ActivityLifecycleCallbacks mActivityLifecycleCallback = new Application.ActivityLifecycleCallbacks() {
            @Override
            public void onActivityCreated(Activity activity, Bundle bundle) {
                if (!mActivityMap.containsKey(activity.getClass().hashCode())) {
                    mActivityMap.put(activity.getClass().hashCode(), activity.getClass().getSimpleName());
                    if (mSpecialActivityName.contains(activity.getClass().getSimpleName())) {
                        mSpecialActivity.add(activity.getClass().hashCode());
                    }
                }
    
                MatrixLog.d(TAG, "activity create:" + activity.getClass().getSimpleName());
            }
    @Override
            public void onActivityStarted(final Activity activity) {
                onShow(activity);
            }
    .....//关键代码
        };
    
    private final ComponentCallbacks2 mComponentCallback = new ComponentCallbacks2() {
            @Override
            public void onTrimMemory(final int i) {
                switch (i) {
                    case TRIM_MEMORY_RUNNING_CRITICAL:
                        break;
                    case TRIM_MEMORY_COMPLETE:
                        break;
                    default:
                        return;
                }
    
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        detectAppMemoryInfo(mShowingActivity, true, i);
                    }
                });
            }
    .....//关键代码
         @Override
            public void onLowMemory() {
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        detectAppMemoryInfo(mShowingActivity, true, LOW_MEMORY_TRIM);
                    }
                });
            }
        };
    

    detectAppMemoryInfo这个我就不多说了
    在activity生命周期的activityStart里面有个onShow方法
    问题:
    没有太懂,为什么对activity做了个IFragmentActivity的判断?
    这个IFragmentActivity是一个Interface,也没有看见哪个activity实现了这个接口。

    detectAppMemoryInfo之后,最终是调用detectAppMemoryInfoImpl
    并且会触发onDetectIssue回调。
    最终由pluginListener.onReportIssue(issue);把内存信息发送出去。

    MemoryCanaryPlugin没有做内存泄露的检测,可能是没必要重复造轮子吧。


    3.性能监控TracePlugin

    这个监控应该是四个角度

        TracePlugin类的四个成员变量
        private FPSTracer mFPSTracer;//帧率
        private EvilMethodTracer mEvilMethodTracer;//应该是耗时方法
        private FrameTracer mFrameTracer;//帧数
        private StartUpTracer mStartUpTracer;//启动速度
    

    初始化

    public void init(Application app, PluginListener listener) {
            super.init(app, listener);
            MatrixLog.i(TAG, "trace plugin init, trace config: %s", mTraceConfig.toString());
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
                MatrixLog.e(TAG, "[FrameBeat] API is low Build.VERSION_CODES.JELLY_BEAN(16), TracePlugin is not supported");
                unSupportPlugin();
                return;
            }
    
            ApplicationLifeObserver.init(app);
    
            mFrameTracer = new FrameTracer(this);//帧数检测是默认开启的
            if (mTraceConfig.isMethodTraceEnable()) {
                mStartUpTracer = new StartUpTracer(this, mTraceConfig);
            }
            if (mTraceConfig.isFPSEnable()) {
                mFPSTracer = new FPSTracer(this, mTraceConfig);
            }
    
            if (mTraceConfig.isMethodTraceEnable()) {
                mEvilMethodTracer = new EvilMethodTracer(this, mTraceConfig);
            }
        }
    

    ApplicationLifeObserver实现了ActivityLifecycleCallbacks接口,内部是监控activity是否在前台。
    start后,重点关注FrameBeat.getInstance().onCreate();
    然后先看mFPSTracer.onCreate();

    public void start() {
            super.start();
            if (!isSupported()) {
                return;
            }
    
            new Handler(Looper.getMainLooper()).post(new Runnable() {
                @Override
                public void run() {
                    FrameBeat.getInstance().onCreate();
                }
            });
    
            if (null != mFPSTracer) {
                mFPSTracer.onCreate();
            }
          //....省略
        }
    

    实际上呢,这个FrameBeat就是借助了Choreographer.FrameCallback
    监控相邻两次 Vsync 事件通知的时间差
    (360的开源方案https://github.com/Qihoo360/ArgusAPM)

    微信自己的公众号也说了
    https://mp.weixin.qq.com/s/W4-1tfepKg2XMYvVn62B-Q

    确实在FrameBeat类,在activity的Resume时间注册这个回调,在pause反注册,doFrame里完成事件的记录。

    public void doFrame(long frameTimeNanos) {
            if (isPause) {
                return;
            }
            if (frameTimeNanos < mLastFrameNanos || mLastFrameNanos <= 0) {
                mLastFrameNanos = frameTimeNanos;
                if (null != mChoreographer) {
                    mChoreographer.postFrameCallback(this);
                }
                return;
            }
    
            if (null != mFrameListeners) {
    
                for (IFrameBeatListener listener : mFrameListeners) {
                    listener.doFrame(mLastFrameNanos, frameTimeNanos);
                }
    
                if (null != mChoreographer) {
                    mChoreographer.postFrameCallback(this);
                }
    
                mLastFrameNanos = frameTimeNanos;
            }
    
        }
    

    由IFrameBeatListener完成回调动作,BaseTracer实现了IFrameBeatListener接口,但是内部是一个空实现,最终由子类FrameTracer来实现真正的统计方法。

    public void doFrame(final long lastFrameNanos, final long frameNanos) {
            if (!isDrawing) {
                return;
            }
            isDrawing = false;
            final int droppedCount = (int) ((frameNanos - lastFrameNanos) / REFRESH_RATE_MS);
            for (final IDoFrameListener listener : mDoFrameListenerList) {
                listener.doFrameSync(lastFrameNanos, frameNanos, getScene(), droppedCount);
                if (null != listener.getHandler()) {
                    listener.getHandler().post(new AsyncDoFrameTask(listener,
                            lastFrameNanos, frameNanos, getScene(), droppedCount));
                }
            }
        }
    

    continue...

    相关文章

      网友评论

        本文标题:腾讯性能检测库Matrix源码阅读

        本文链接:https://www.haomeiwen.com/subject/sbwlwqtx.html