赞
踩
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
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。