GL&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);
                    }
                }
            }
 

深入解析Linux进程内存:VSS、RSS、PSS、USS及查看方式_pss rss-CSDN博客


/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

ION

Android ION 相关信息查看方法_kernel查看ion-CSDN博客

Android meminfo 查看方法及解析

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

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
EGL, OpenGL和GSL是与图形编程相关的术语。EGL是嵌入式系统图形库,OpenGL是用于渲染2D和3D图形的图形API,GSL则是GNU科学库。它们之间的关系如下: EGL (Embedded-System Graphics Library) 是一个用于管理嵌入式系统中图形显示和窗口系统的库。它提供了与底层图形驱动程序的接口,允许应用程序创建和管理图形表面。 OpenGL (Open Graphics Library) 是一个跨平台的图形API,用于渲染2D和3D图形。它定义了一套函数和命令,用于描述和操作图形对象,如点、线、三角形和纹理等。通过OpenGL,开发者可以利用硬件加速来实现高性能的图形渲染。 GSL (GNU Scientific Library) 是一个用于数值计算和科学计算的C和C++库。它提供了许多常用的数学函数和算法,包括线性代数、特殊函数、傅里叶变换、随机数生成等。 所以,EGL是一个图形库,用于管理嵌入式系统中的图形显示和窗口系统;OpenGL是一个图形API,用于渲染2D和3D图形;而GSL是一个数值计算和科学计算的库。 : 参考资料中提到,如果你在编译过程中遇到了"Could NOT find OpenGL (missing: OPENGL_glx_LIBRARY)"的问题,你可以尝试重新安装libgl1-mesa-dev库来解决。你可以使用以下命令来重新安装该库:sudo apt-get install --reinstall libgl1-mesa-dev。 : 参考资料中还提到,你也可以在你的CMakeLists.txt文件中设置OpenGL_GL_PREFERENCE变量为"GLVND",以解决该问题。设置该变量后,CMake会使用GLVND(OpenGL Vendor-Neutral Dispatch)来选择OpenGL驱动程序。 综上所述,EGL是用于管理嵌入式系统中图形显示和窗口系统的库,OpenGL是一个用于渲染2D和3D图形的图形API,GSL是一个用于数值计算和科学计算的库。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值