当前位置:   article > 正文

GL&EGL mtrack

egl mtrack

探讨Android内存管理 - 简书

GL mtrack is driver-reported GL memory usage. It's primarily the sum of GL texture sizes, GL command buffers, fixed global driver RAM overheads, etc.

EGL mtrack is gralloc memory usage. It's primarily the sum of the SurfaceView/TextureView.

Graphics 内存部分包括 Gfx dev 、EGL mtrack、GL mtrack 三部分

gfx dev:/d/proc/<pid>/smaps 文件里 tag 为 “/dev/kgsl-3d0” 的内存空间总和,其与应用所申请的 OpenGL 资源(如纹理)大小有直接联系,所申请的资源越多越大,该项统计就会越大

gl mtrack:/d/kgsl/proc/<pid>/mem 文件里统计的类型为 gpumem 的条目,其含义是GPU 驱动分配给应用的显存资源。OpenGL 资源实际所占用的显存空间则与gfx dev项有关。驱动会多分配多少显存给应用这个不得而知,但毫无疑问,应用申请的 OpenGL 资源越多,该项统计也会越大

egl mtrack:各平台含义一致,Graphicbuffer 占用的显存空间。window、surfaceview、textureview、hardware bitmap (android O),或其它直接使用 graphicbuffer 的方式都统计在这项里

app申请的buffer内存,由于需要送到sf、hwc进行合成,因此这部分内存按照比例分配给所使用的的进程,即PSS内存

高通平台 GL&EGL mtrack

/vendor/etc/init
 /vendor/bin/hw/vendor.qti.hardware.memtrack-service
system/lib64/libmemtrack.so

USS是private clean内存和private dirty内存的总和,但分开跟踪private clean内存和private dirty内存可能非常有用,因为private clean内存更容易回收(在本例中,clean意味着它在从磁盘读取时未被修改)。RSS是所有private和shared、clean和dirty内存的总和
        if (is_swappable && (usage.pss > 0)) {
            float sharing_proportion = 0.0;
            if ((usage.shared_clean > 0) || (usage.shared_dirty > 0)) {
                sharing_proportion = (usage.pss - usage.uss) / (usage.shared_clean + usage.shared_dirty);
            }
            swapable_pss = (sharing_proportion * usage.shared_clean) + usage.private_clean;
        }
        
 

/proc/stat
/proc/$pid/stat
https://www.cnblogs.com/wangfengju/p/6172440.html


    void updateCpuStatsNow() {
        synchronized (mProcessCpuTracker) {
            mProcessCpuMutexFree.set(false);
            final long now = SystemClock.uptimeMillis();
            boolean haveNewCpuStats = false;

            if (MONITOR_CPU_USAGE &&
                    mLastCpuTime.get() < (now-MONITOR_CPU_MIN_TIME)) {
                mLastCpuTime.set(now);
                mProcessCpuTracker.update();
                if (mProcessCpuTracker.hasGoodLastStats()) {
                    haveNewCpuStats = true;
                    //Slog.i(TAG, mProcessCpu.printCurrentState());
                    //Slog.i(TAG, "Total CPU usage: "
                    //        + mProcessCpu.getTotalCpuPercent() + "%");

                    // Slog the cpu usage if the property is set.
                    if ("true".equals(SystemProperties.get("events.cpu"))) {
                        int user = mProcessCpuTracker.getLastUserTime();
                        int system = mProcessCpuTracker.getLastSystemTime();
                        int iowait = mProcessCpuTracker.getLastIoWaitTime();
                        int irq = mProcessCpuTracker.getLastIrqTime();
                        int softIrq = mProcessCpuTracker.getLastSoftIrqTime();
                        int idle = mProcessCpuTracker.getLastIdleTime();

                        int total = user + system + iowait + irq + softIrq + idle;
                        if (total == 0) total = 1;

                        EventLogTags.writeCpu(
                                ((user + system + iowait + irq + softIrq) * 100) / total,
                                (user * 100) / total,
                                (system * 100) / total,
                                (iowait * 100) / total,
                                (irq * 100) / total,
                                (softIrq * 100) / total);
                    }
                }
            }
 


/proc/loadavg
前三个数字是1、5、15分钟内进程队列中平均进程数,包括正在运行的进程+准备好等待运行的进程。 第四个数字分子表示正在运行的进程数,分母是进程总数。 最后一个数字是最近运行的进程ID号

/proc/uptime

解读
https://www.jianshu.com/p/2fb2eca190cb
https://cloud.tencent.com/developer/article/1576347

/system/memory/libmeminfo/
/system/memory/libmemtrack/
https://blog.csdn.net/congqingbin/article/details/132460644

在Android S之前,memtrack HAL模块是默认开启的,而在Android S及之后的版本,需要OEM开启.
android S:
device/qcom/vendor-common/base.mk
在下方取消注释以启用 memtrack 服务。
#PRODUCT_PACKAGES += \

vendor.qti.hardware.memtrack-service

dumpsys procstats

1、procstats 工具是Android自带的用来分析应用的随时间变化的内存使用 (相对一个时间点的内存快照 meminfo来说),它会输出应用的运行时的 PSS、USS数据,包括最小值、平均值、最大值

2、输入:为了获取应用最后3个小时内的内存使用数据,就可以使用这个命令:

adb shell dumpsys procstats  --hours 3 

3、输出:从下面的例子我们可以看出,百分比显示出应用多少百分比的时间在运行,而数字按照(最小PSS-平均PSS-最大PSS/最小USS-平均USS-最大USS)的格式显示出PSS和USS


输出字段解释
百分比:表示在总的时间内,进程在各种状态下的消耗
例如,100%,就指在这段时间内,这个进程是一直处于运行当中的
TOTAL:表示了进程的综合占用情况
lmp Fg:加载到前台
Service:标识了是否是服务
Persistent:标识了是否一直驻留在内存当中,与Service一样,表示内存进驻的级别
Top:标识了是否是顶层进程
Receiver:标识了是否是广播进程

gl&vulkan
https://new.qq.com/rain/a/20220425A02BMQ00

dumpsys meminfo  

pw.print("Total RAM: "); pw.print(stringifyKBSize(memInfo.getTotalSizeKb()));

对应  /proc/meminfo  中 /proc/meminfo

                    pw.print(" Free RAM: ");
                    pw.print(stringifyKBSize(cachedPss + memInfo.getCachedSizeKb()
                            + memInfo.getFreeSizeKb()));
                    pw.print(" (");
                    pw.print(stringifyKBSize(cachedPss));
                    pw.print(" cached pss + ");
                    pw.print(stringifyKBSize(memInfo.getCachedSizeKb()));
                    pw.print(" cached kernel + ");
                    pw.print(stringifyKBSize(memInfo.getFreeSizeKb()));
                    pw.println(" free)");

    /**
     * Amount of RAM that the kernel is being used for caches, not counting caches
     * that are mapped in to processes.
     */
    public long getCachedSizeKb() {
        long kReclaimable = mInfos[Debug.MEMINFO_KRECLAIMABLE];

        // Note: MEMINFO_KRECLAIMABLE includes MEMINFO_SLAB_RECLAIMABLE and ION pools.
        // Fall back to using MEMINFO_SLAB_RECLAIMABLE in case of older kernels that do
        // not include KReclaimable meminfo field.
        if (kReclaimable == 0) {
            kReclaimable = mInfos[Debug.MEMINFO_SLAB_RECLAIMABLE];
        }
        return mInfos[Debug.MEMINFO_BUFFERS] + kReclaimable
                + mInfos[Debug.MEMINFO_CACHED] - mInfos[Debug.MEMINFO_MAPPED];
    }

cached pss   对应cached 应用pss 总和

cached kernel   对应 /proc/meminfo  中 KReclaimable:(或SReclaimable::)+ Buffers: + Cached: -Mapped:

            long kernelUsed = memInfo.getKernelUsedSizeKb();  
            final long ionHeap = Debug.getIonHeapsSizeKb();
            if (ionHeap > 0) {
                final long ionMapped = Debug.getIonMappedSizeKb();
                final long ionUnmapped = ionHeap - ionMapped;
                final long ionPool = Debug.getIonPoolsSizeKb();
                pw.print("      ION: ");
                        pw.print(stringifyKBSize(ionHeap + ionPool));
                        pw.print(" (");
                        pw.print(stringifyKBSize(ionMapped));
                        pw.print(" mapped + ");
                        pw.print(stringifyKBSize(ionUnmapped));
                        pw.print(" unmapped + ");
                        pw.print(stringifyKBSize(ionPool));
                        pw.println(" pools)");
                // Note: mapped ION memory is not accounted in PSS due to VM_PFNMAP flag being
                // set on ION VMAs, therefore consider the entire ION heap as used kernel memory
                kernelUsed += ionHeap;
            }

    /**
     * Amount of RAM that is in use by the kernel for actual allocations.
     */
    public long getKernelUsedSizeKb() {
        long size = mInfos[Debug.MEMINFO_SHMEM] + mInfos[Debug.MEMINFO_SLAB_UNRECLAIMABLE]
                + mInfos[Debug.MEMINFO_VM_ALLOC_USED] + mInfos[Debug.MEMINFO_PAGE_TABLES];
        if (!Debug.isVmapStack()) {
            size += mInfos[Debug.MEMINFO_KERNEL_STACK];
        }
        return size;
    }

kernel占用:Shmem:+SUnreclaim:+VmallocUsed:+KernelStack:+PageTables: + /sys/kernel/ion/total_heaps_kb

ION:/sys/kernel/ion/total_heaps_kb + /sys/kernel/ion/total_pools_kb

ION mapper 对应/proc/$pid/maps 中 /dmabuf: 段(???/sys/kernel/debug/dma_buf/bufinfo)

ION UNMAPP :/sys/kernel/ion/total_heaps_kb - ION mapper

static jlong android_os_Debug_getIonHeapsSizeKb(JNIEnv* env, jobject clazz) {
    jlong heapsSizeKb = 0;
    uint64_t size;

    if (meminfo::ReadIonHeapsSizeKb(&size)) {
        heapsSizeKb = size;
    }

    return heapsSizeKb;
}

static jlong android_os_Debug_getIonPoolsSizeKb(JNIEnv* env, jobject clazz) {
    jlong poolsSizeKb = 0;
    uint64_t size;

    if (meminfo::ReadIonPoolsSizeKb(&size)) {
        poolsSizeKb = size;
    }

    return poolsSizeKb;
}

    /**
     * Return ION memory mapped by processes in kB.
     * Notes:
     *  * Warning: Might impact performance as it reads /proc/<pid>/maps files for each process.
     *
     * @hide
     */
    public static native long getIonMappedSizeKb();

 97 // Parse /proc/vmallocinfo and return total physical memory mapped
 98 // in vmalloc area by the kernel. Note that this deliberately ignores binder buffers. They are
 99 // _always_ mapped in a process and are counted for in each process.
100 uint64_t ReadVmallocInfo(const char* path = "/proc/vmallocinfo");
101 
102 // Read ION heaps allocation size in kb
103 bool ReadIonHeapsSizeKb(
104     uint64_t* size, const std::string& path = "/sys/kernel/ion/total_heaps_kb");
105 
106 // Read ION pools allocation size in kb
107 bool ReadIonPoolsSizeKb(
108     uint64_t* size, const std::string& path = "/sys/kernel/ion/total_pools_kb");

lostRAM &used RAM

lostRAM = /proc/meminfo 下的MemTotal: - (所以应用pss - 所有swapPss) - /proc/meminfo 下的MemFree: - 内核cached - 内核使用 -  zram总量

内核cached 为

cached kernel   对应 /proc/meminfo  中 KReclaimable:(或SReclaimable::)+ Buffers: + Cached: -Mapped:

Used RAM: = 所有应用pss - 所有后台应用pss + 内核占用

意思就是杀掉所有cache 应用,回收所有内核cache ,就只有非cache 应用pss + 内核占用这两部分内存占用

            final long lostRAM = memInfo.getTotalSizeKb() - (totalPss - totalSwapPss)
                    - memInfo.getFreeSizeKb() - memInfo.getCachedSizeKb()
                    - kernelUsed - memInfo.getZramTotalSizeKb();
            if (!opts.isCompact) {
                pw.print(" Used RAM: "); pw.print(stringifyKBSize(totalPss - cachedPss
                        + kernelUsed)); pw.print(" (");
                pw.print(stringifyKBSize(totalPss - cachedPss)); pw.print(" used pss + ");
                pw.print(stringifyKBSize(kernelUsed)); pw.print(" kernel)\n");
                pw.print(" Lost RAM: "); pw.println(stringifyKBSize(lostRAM));
            } else {
                pw.print("lostram,"); pw.println(lostRAM);
            }

zram

if (memInfo.getZramTotalSizeKb() != 0) {
                    if (!opts.isCompact) {
                        pw.print("     ZRAM: ");
                        pw.print(stringifyKBSize(memInfo.getZramTotalSizeKb()));
                                pw.print(" physical used for ");
                                pw.print(stringifyKBSize(memInfo.getSwapTotalSizeKb()
                                        - memInfo.getSwapFreeSizeKb()));
                                pw.print(" in swap (");
                                pw.print(stringifyKBSize(memInfo.getSwapTotalSizeKb()));
                                pw.println(" total swap)");
                    } 

KSM

                final long[] ksm = getKsmInfo();
                if (!opts.isCompact) {
                    if (ksm[KSM_SHARING] != 0 || ksm[KSM_SHARED] != 0 || ksm[KSM_UNSHARED] != 0
                            || ksm[KSM_VOLATILE] != 0) {
                        pw.print("      KSM: "); pw.print(stringifyKBSize(ksm[KSM_SHARING]));
                                pw.print(" saved from shared ");
                                pw.print(stringifyKBSize(ksm[KSM_SHARED]));
                        pw.print("           "); pw.print(stringifyKBSize(ksm[KSM_UNSHARED]));
                                pw.print(" unshared; ");
                                pw.print(stringifyKBSize(
                                             ksm[KSM_VOLATILE])); pw.println(" volatile");
                    }

                    pw.print("   Tuning: ");
                    pw.print(ActivityManager.staticGetMemoryClass());
                    pw.print(" (large ");
                    pw.print(ActivityManager.staticGetLargeMemoryClass());
                    pw.print("), oom ");
                    pw.print(stringifySize(
                                mProcessList.getMemLevel(ProcessList.CACHED_APP_MAX_ADJ), 1024));
                    pw.print(", restore limit ");
                    pw.print(stringifyKBSize(mProcessList.getCachedRestoreThresholdKb()));
                    if (ActivityManager.isLowRamDeviceStatic()) {
                        pw.print(" (low-ram)");
                    }
                    if (ActivityManager.isHighEndGfx()) {
                        pw.print(" (high-end-gfx)");
                    }
                    pw.println();

  Tuning: 512 (large 512), oom   322,560K, restore limit   107,520K (high-end-gfx)

512 (large 512)  dalvike heap 

oom  cache 应用水位    getMemLevel(ProcessList.CACHED_APP_MAX_ADJ)

    static public int staticGetMemoryClass() {
        // Really brain dead right now -- just take this from the configured
        // vm heap size, and assume it is in megabytes and thus ends with "m".
        String vmHeapSize = SystemProperties.get("dalvik.vm.heapgrowthlimit", "");
        if (vmHeapSize != null && !"".equals(vmHeapSize)) {
            return Integer.parseInt(vmHeapSize.substring(0, vmHeapSize.length()-1));
        }
        return staticGetLargeMemoryClass();
    }

    static public int staticGetLargeMemoryClass() {
        // Really brain dead right now -- just take this from the configured
        // vm heap size, and assume it is in megabytes and thus ends with "m".
        String vmHeapSize = SystemProperties.get("dalvik.vm.heapsize", "16m");
        return Integer.parseInt(vmHeapSize.substring(0, vmHeapSize.length() - 1));
    }

    

restore limit   107,520K

        // The maximum size we will restore a process from cached to background, when under
        // memory duress, is 1/3 the size we have reserved for kernel caches and other overhead
        // before killing background processes.
        mCachedRestoreLevel = (getMemLevel(ProcessList.CACHED_APP_MAX_ADJ) / 1024) / 3;

            writeLmkd(buf, null);
            SystemProperties.set("sys.sysctl.extra_free_kbytes", Integer.toString(reserve));


 

system_server_lowmem

Process: system_server
Subject: Low on memory -- 2048MB total / 250MB system / 20MB car 20MB process / 30MB

当没有后台进程金辉打印

am_low_memory: 6

Andriod Low on memory 打印原理分析-CSDN博客

qnx下执行
echo gpu_set_log_level 4 > /dev/kgsl-control
使能 1000ms  采集
echo gpubusystats 1000 > /dev/kgsl-control
使能perf模式
echo gpu_perf_governor 1 > /dev/kgsl-control 
打印出使用率
slog2info -b KGSL -w | grep measurement          -----8155命令

slog2info -b KGSL -w | grep utilization     -------有些平台

qnx 下
echo pmemtbl >/dev/kgsl-control
pull 出/var/log/pmemtbl_control.txt

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/303609
推荐阅读
相关标签
  

闽ICP备14008679号