美文网首页
云米客户端APM性能监控组件分析(四)

云米客户端APM性能监控组件分析(四)

作者: 捉影T_T900 | 来源:发表于2020-04-09 15:55 被阅读0次

    上一篇文章已经分析了画面帧率的监控原理,现在来分析内存使用的原理和技巧。

    按惯例,先了解一下计算机内存方面的基本知识。作为计算机三大件中的一个角色(CPU、内存、硬盘),内存就像一个缓冲区,让CPU更快地从内存中获得数据,让硬盘更方便地将数据写入到内存中(硬盘的IO操作相对耗时)。但这个缓冲区不是无限量的大,有一定的空间限制,如果写入的数据太多,会将缓冲区填满,那程序就会崩溃(OOM)。即使不填满,剩余不多的时候也会影响程序的正常运行。

    问题一:我通过什么方式来获得系统运行时的内存数据?

    我现在知道内存的作用了,但我不知道从哪里、通过什么方式获得这些数据。这里用到android.os.Debug这个对象。下面是头部介绍。

    /**
     * Provides various debugging methods for Android applications, including
     * tracing and allocation counts.
     * <p><strong>Logging Trace Files</strong></p>
     * <p>Debug can create log files that give details about an application, such as
     * a call stack and start/stop times for any running methods. See <a
     * href="{@docRoot}studio/profile/traceview.html">Inspect Trace Logs with
     * Traceview</a> for information about reading trace files. To start logging
     * trace files, call one of the startMethodTracing() methods. To stop tracing,
     * call {@link #stopMethodTracing()}.
     */
    

    可以通过这个对象获得程序运行的各种信息。

    另外在ActivityManager中也有一个方法,可以获得指定进程的内存使用情况,返回的也是Debug对象。

        /**
         * Return information about the memory usage of one or more processes.
         *
         * <p><b>Note: this method is only intended for debugging or building
         * a user-facing process management UI.</b></p>
         *
         * @param pids The pids of the processes whose memory usage is to be
         * retrieved.
         * @return Returns an array of memory information, one for each
         * requested pid.
         */
        public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids) {
            try {
                return getService().getProcessMemoryInfo(pids);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
    

    关于系统的内存信息数据,可以在【/proc/meminfo】这个文件中获取,这个文件会实时地更新整个系统地内存数据并写入到该文件中。所以可以直接读这个文件的内容来获得内存信息。

    问题二:你说的我都看得懂,但我还是不知道怎么写,你直接写出来让我copy吧,我太难了

    内存信息采样没必要做到很频繁,毕竟大部分都不是高频运算程序,即使是游戏,也只是实时对战的时候才是高频运算,摸摸自己的手机就知道。所以可以限定1个小时采样一次。

        /**
         * 获取当前内存信息,耗时操作,再子线程操作
         * @return
         */
        private MemoryInfo getMemoryInfo() {
    
            int pid = android.os.Process.myPid();
    
            Context context = Manager.getContext();
            ActivityManager activityManager = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);
            Debug.MemoryInfo[] memoryInfoArray = activityManager.getProcessMemoryInfo(new int[]{pid});
    
            long currentUsedMem = memoryInfoArray[0].getTotalPrivateDirty();
            long totalMem = getTotalMem();
            if (Manager.isDebug()) {
                ApmLogX.d(APM_TAG, SUB_TAG,
                        "当前应用使用内存:" + Formatter.formatFileSize(context, currentUsedMem * 1024) + "的内存" +
                        "  系统总内存:" + Formatter.formatFileSize(context, totalMem * 1024));
            }
    
            Debug.MemoryInfo info = new Debug.MemoryInfo();
            Debug.getMemoryInfo(info);
            if (Manager.isDebug()) {
                ApmLogX.d(APM_TAG, SUB_TAG,
                        "currentProcess:" + ProcessUtils.getCurrentProcessName()
                                + "  dalvikPss:" + info.dalvikPss
                                + "  nativePss:" + info.nativePss
                                + "  otherPass:" + info.otherPss
                                + "  totalPss:" + info.getTotalPss());
            }
            return new MemoryInfo(ProcessUtils.getCurrentProcessName(), currentUsedMem, totalMem, info.dalvikPss, info.nativePss, info.otherPss, info.getTotalPss());
        }
    
    
        private long getTotalMem() {
            String meminfoFile = "/proc/meminfo";
            long initial_memory = 0;
    
            try {
                FileReader localFileReader = new FileReader(meminfoFile);
                BufferedReader bufferedReader = new BufferedReader(localFileReader, 8192);
                String content = bufferedReader.readLine(); // 只读第一行,获得系统总内存信息
                String[] arrayOfString = content.split("\\s+");
                for (String text : arrayOfString) {
                    Log.i(SUB_TAG, "value:" + text);
                }
                initial_memory = Long.parseLong(arrayOfString[1]);
                bufferedReader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
    
            return initial_memory;
        }
    

    这里又延伸出一个细节,PSS是什么?

    PSS学术名称叫做“比例集大小(proportional set size)”

    是一个系统给出来地分数,用于判断是否需要将这个运行中的程序杀死,如果总得分非常高,那系统很可能会立刻将这个程序kill掉。

    多高才算高?这个不知道,但系统会做综合判断。好了,整个运行时的内存信息已经获取完毕,Debug对象内部还有很多信息可以获取,想拿什么就去拿什么吧...

    未完待续......

    相关文章

      网友评论

          本文标题:云米客户端APM性能监控组件分析(四)

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