Merge "Read per-process GPU memory when pulling ProcessMemorySnapshot"
This commit is contained in:
committed by
Android (Google) Code Review
commit
fce46978ff
@@ -18,9 +18,9 @@ package com.android.internal.os;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
|
||||
/** Wrapper around libdmabufinfo. */
|
||||
public final class DmabufInfoReader {
|
||||
private DmabufInfoReader() {}
|
||||
/** JNI wrapper around libmeminfo for kernel memory allocation stats (dmabufs, gpu driver). */
|
||||
public final class KernelAllocationStats {
|
||||
private KernelAllocationStats() {}
|
||||
|
||||
/** Process dma-buf stats. */
|
||||
public static final class ProcessDmabuf {
|
||||
@@ -47,5 +47,19 @@ public final class DmabufInfoReader {
|
||||
* stats could not be read.
|
||||
*/
|
||||
@Nullable
|
||||
public static native ProcessDmabuf getProcessStats(int pid);
|
||||
public static native ProcessDmabuf getDmabufAllocations(int pid);
|
||||
|
||||
/** Pid to gpu memory size. */
|
||||
public static final class ProcessGpuMem {
|
||||
public final int pid;
|
||||
public final int gpuMemoryKb;
|
||||
|
||||
ProcessGpuMem(int pid, int gpuMemoryKb) {
|
||||
this.pid = pid;
|
||||
this.gpuMemoryKb = gpuMemoryKb;
|
||||
}
|
||||
}
|
||||
|
||||
/** Return list of pid to gpu memory size. */
|
||||
public static native ProcessGpuMem[] getGpuAllocations();
|
||||
}
|
||||
@@ -210,8 +210,8 @@ cc_library_shared {
|
||||
"com_android_internal_content_om_OverlayConfig.cpp",
|
||||
"com_android_internal_net_NetworkUtilsInternal.cpp",
|
||||
"com_android_internal_os_ClassLoaderFactory.cpp",
|
||||
"com_android_internal_os_DmabufInfoReader.cpp",
|
||||
"com_android_internal_os_FuseAppLoop.cpp",
|
||||
"com_android_internal_os_KernelAllocationStats.cpp",
|
||||
"com_android_internal_os_KernelCpuBpfTracking.cpp",
|
||||
"com_android_internal_os_KernelCpuTotalBpfMapReader.cpp",
|
||||
"com_android_internal_os_KernelCpuUidBpfMapReader.cpp",
|
||||
|
||||
@@ -197,8 +197,8 @@ extern int register_com_android_internal_content_NativeLibraryHelper(JNIEnv *env
|
||||
extern int register_com_android_internal_content_om_OverlayConfig(JNIEnv *env);
|
||||
extern int register_com_android_internal_net_NetworkUtilsInternal(JNIEnv* env);
|
||||
extern int register_com_android_internal_os_ClassLoaderFactory(JNIEnv* env);
|
||||
extern int register_com_android_internal_os_DmabufInfoReader(JNIEnv* env);
|
||||
extern int register_com_android_internal_os_FuseAppLoop(JNIEnv* env);
|
||||
extern int register_com_android_internal_os_KernelAllocationStats(JNIEnv* env);
|
||||
extern int register_com_android_internal_os_KernelCpuBpfTracking(JNIEnv* env);
|
||||
extern int register_com_android_internal_os_KernelCpuTotalBpfMapReader(JNIEnv* env);
|
||||
extern int register_com_android_internal_os_KernelCpuUidBpfMapReader(JNIEnv *env);
|
||||
@@ -1655,8 +1655,8 @@ static const RegJNIRec gRegJNI[] = {
|
||||
REG_JNI(register_android_security_Scrypt),
|
||||
REG_JNI(register_com_android_internal_content_F2fsUtils),
|
||||
REG_JNI(register_com_android_internal_content_NativeLibraryHelper),
|
||||
REG_JNI(register_com_android_internal_os_DmabufInfoReader),
|
||||
REG_JNI(register_com_android_internal_os_FuseAppLoop),
|
||||
REG_JNI(register_com_android_internal_os_KernelAllocationStats),
|
||||
REG_JNI(register_com_android_internal_os_KernelCpuBpfTracking),
|
||||
REG_JNI(register_com_android_internal_os_KernelCpuTotalBpfMapReader),
|
||||
REG_JNI(register_com_android_internal_os_KernelCpuUidBpfMapReader),
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <dmabufinfo/dmabufinfo.h>
|
||||
#include "core_jni_helpers.h"
|
||||
|
||||
namespace android {
|
||||
|
||||
static jobject DmabufInfoReader_getProcessStats(JNIEnv *env, jobject, jint pid) {
|
||||
std::vector<dmabufinfo::DmaBuffer> buffers;
|
||||
if (!dmabufinfo::ReadDmaBufMapRefs(pid, &buffers)) {
|
||||
return nullptr;
|
||||
}
|
||||
jint mappedSize = 0;
|
||||
jint mappedCount = buffers.size();
|
||||
for (const auto &buffer : buffers) {
|
||||
mappedSize += buffer.size();
|
||||
}
|
||||
mappedSize /= 1024;
|
||||
|
||||
jint retainedSize = -1;
|
||||
jint retainedCount = -1;
|
||||
if (dmabufinfo::ReadDmaBufFdRefs(pid, &buffers)) {
|
||||
retainedCount = buffers.size();
|
||||
retainedSize = 0;
|
||||
for (const auto &buffer : buffers) {
|
||||
retainedSize += buffer.size();
|
||||
}
|
||||
retainedSize /= 1024;
|
||||
}
|
||||
|
||||
jclass clazz = FindClassOrDie(env, "com/android/internal/os/DmabufInfoReader$ProcessDmabuf");
|
||||
jmethodID constructID = GetMethodIDOrDie(env, clazz, "<init>", "(IIII)V");
|
||||
return env->NewObject(clazz, constructID, retainedSize, retainedCount, mappedSize, mappedCount);
|
||||
}
|
||||
|
||||
static const JNINativeMethod methods[] = {
|
||||
{"getProcessStats", "(I)Lcom/android/internal/os/DmabufInfoReader$ProcessDmabuf;",
|
||||
(void *)DmabufInfoReader_getProcessStats},
|
||||
};
|
||||
|
||||
int register_com_android_internal_os_DmabufInfoReader(JNIEnv *env) {
|
||||
return RegisterMethodsOrDie(env, "com/android/internal/os/DmabufInfoReader", methods,
|
||||
NELEM(methods));
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
97
core/jni/com_android_internal_os_KernelAllocationStats.cpp
Normal file
97
core/jni/com_android_internal_os_KernelAllocationStats.cpp
Normal file
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include <dmabufinfo/dmabufinfo.h>
|
||||
#include <jni.h>
|
||||
#include <meminfo/sysmeminfo.h>
|
||||
|
||||
#include "core_jni_helpers.h"
|
||||
|
||||
namespace {
|
||||
static jclass gProcessDmabufClazz;
|
||||
static jmethodID gProcessDmabufCtor;
|
||||
static jclass gProcessGpuMemClazz;
|
||||
static jmethodID gProcessGpuMemCtor;
|
||||
} // namespace
|
||||
|
||||
namespace android {
|
||||
|
||||
static jobject KernelAllocationStats_getDmabufAllocations(JNIEnv *env, jobject, jint pid) {
|
||||
std::vector<dmabufinfo::DmaBuffer> buffers;
|
||||
if (!dmabufinfo::ReadDmaBufMapRefs(pid, &buffers)) {
|
||||
return nullptr;
|
||||
}
|
||||
jint mappedSize = 0;
|
||||
jint mappedCount = buffers.size();
|
||||
for (const auto &buffer : buffers) {
|
||||
mappedSize += buffer.size();
|
||||
}
|
||||
mappedSize /= 1024;
|
||||
|
||||
jint retainedSize = -1;
|
||||
jint retainedCount = -1;
|
||||
if (dmabufinfo::ReadDmaBufFdRefs(pid, &buffers)) {
|
||||
retainedCount = buffers.size();
|
||||
retainedSize = 0;
|
||||
for (const auto &buffer : buffers) {
|
||||
retainedSize += buffer.size();
|
||||
}
|
||||
retainedSize /= 1024;
|
||||
}
|
||||
return env->NewObject(gProcessDmabufClazz, gProcessDmabufCtor, retainedSize, retainedCount,
|
||||
mappedSize, mappedCount);
|
||||
}
|
||||
|
||||
static jobject KernelAllocationStats_getGpuAllocations(JNIEnv *env) {
|
||||
std::unordered_map<uint32_t, uint64_t> out;
|
||||
meminfo::ReadPerProcessGpuMem(&out);
|
||||
jobjectArray result = env->NewObjectArray(out.size(), gProcessGpuMemClazz, nullptr);
|
||||
if (result == NULL) {
|
||||
jniThrowRuntimeException(env, "Cannot create result array");
|
||||
return nullptr;
|
||||
}
|
||||
int idx = 0;
|
||||
for (const auto &entry : out) {
|
||||
jobject pidStats =
|
||||
env->NewObject(gProcessGpuMemClazz, gProcessGpuMemCtor, entry.first, entry.second);
|
||||
env->SetObjectArrayElement(result, idx, pidStats);
|
||||
env->DeleteLocalRef(pidStats);
|
||||
++idx;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static const JNINativeMethod methods[] = {
|
||||
{"getDmabufAllocations", "(I)Lcom/android/internal/os/KernelAllocationStats$ProcessDmabuf;",
|
||||
(void *)KernelAllocationStats_getDmabufAllocations},
|
||||
{"getGpuAllocations", "()[Lcom/android/internal/os/KernelAllocationStats$ProcessGpuMem;",
|
||||
(void *)KernelAllocationStats_getGpuAllocations},
|
||||
};
|
||||
|
||||
int register_com_android_internal_os_KernelAllocationStats(JNIEnv *env) {
|
||||
int res = RegisterMethodsOrDie(env, "com/android/internal/os/KernelAllocationStats", methods,
|
||||
NELEM(methods));
|
||||
jclass clazz =
|
||||
FindClassOrDie(env, "com/android/internal/os/KernelAllocationStats$ProcessDmabuf");
|
||||
gProcessDmabufClazz = MakeGlobalRefOrDie(env, clazz);
|
||||
gProcessDmabufCtor = GetMethodIDOrDie(env, gProcessDmabufClazz, "<init>", "(IIII)V");
|
||||
|
||||
clazz = FindClassOrDie(env, "com/android/internal/os/KernelAllocationStats$ProcessGpuMem");
|
||||
gProcessGpuMemClazz = MakeGlobalRefOrDie(env, clazz);
|
||||
gProcessGpuMemCtor = GetMethodIDOrDie(env, gProcessGpuMemClazz, "<init>", "(II)V");
|
||||
return res;
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
@@ -172,6 +172,7 @@ import android.util.Log;
|
||||
import android.util.Pair;
|
||||
import android.util.Slog;
|
||||
import android.util.SparseArray;
|
||||
import android.util.SparseIntArray;
|
||||
import android.util.StatsEvent;
|
||||
import android.util.proto.ProtoOutputStream;
|
||||
import android.view.Display;
|
||||
@@ -183,7 +184,7 @@ import com.android.internal.os.BackgroundThread;
|
||||
import com.android.internal.os.BatterySipper;
|
||||
import com.android.internal.os.BatteryStatsHelper;
|
||||
import com.android.internal.os.BinderCallsStats.ExportedCallStat;
|
||||
import com.android.internal.os.DmabufInfoReader;
|
||||
import com.android.internal.os.KernelAllocationStats;
|
||||
import com.android.internal.os.KernelCpuBpfTracking;
|
||||
import com.android.internal.os.KernelCpuThreadReader;
|
||||
import com.android.internal.os.KernelCpuThreadReaderDiff;
|
||||
@@ -425,7 +426,6 @@ public class StatsPullAtomService extends SystemService {
|
||||
private final Object mSystemUptimeLock = new Object();
|
||||
private final Object mProcessMemoryStateLock = new Object();
|
||||
private final Object mProcessMemoryHighWaterMarkLock = new Object();
|
||||
private final Object mProcessMemorySnapshotLock = new Object();
|
||||
private final Object mSystemIonHeapSizeLock = new Object();
|
||||
private final Object mIonHeapSizeLock = new Object();
|
||||
private final Object mProcessSystemIonHeapSizeLock = new Object();
|
||||
@@ -563,9 +563,7 @@ public class StatsPullAtomService extends SystemService {
|
||||
return pullProcessMemoryHighWaterMarkLocked(atomTag, data);
|
||||
}
|
||||
case FrameworkStatsLog.PROCESS_MEMORY_SNAPSHOT:
|
||||
synchronized (mProcessMemorySnapshotLock) {
|
||||
return pullProcessMemorySnapshotLocked(atomTag, data);
|
||||
}
|
||||
return pullProcessMemorySnapshot(atomTag, data);
|
||||
case FrameworkStatsLog.SYSTEM_ION_HEAP_SIZE:
|
||||
synchronized (mSystemIonHeapSizeLock) {
|
||||
return pullSystemIonHeapSizeLocked(atomTag, data);
|
||||
@@ -2218,10 +2216,16 @@ public class StatsPullAtomService extends SystemService {
|
||||
);
|
||||
}
|
||||
|
||||
int pullProcessMemorySnapshotLocked(int atomTag, List<StatsEvent> pulledData) {
|
||||
int pullProcessMemorySnapshot(int atomTag, List<StatsEvent> pulledData) {
|
||||
List<ProcessMemoryState> managedProcessList =
|
||||
LocalServices.getService(ActivityManagerInternal.class)
|
||||
.getMemoryStateForProcesses();
|
||||
KernelAllocationStats.ProcessGpuMem[] gpuAllocations =
|
||||
KernelAllocationStats.getGpuAllocations();
|
||||
SparseIntArray gpuMemPerPid = new SparseIntArray(gpuAllocations.length);
|
||||
for (KernelAllocationStats.ProcessGpuMem processGpuMem : gpuAllocations) {
|
||||
gpuMemPerPid.put(processGpuMem.pid, processGpuMem.gpuMemoryKb);
|
||||
}
|
||||
for (ProcessMemoryState managedProcess : managedProcessList) {
|
||||
final MemorySnapshot snapshot = readMemorySnapshotFromProcfs(managedProcess.pid);
|
||||
if (snapshot == null) {
|
||||
@@ -2230,7 +2234,8 @@ public class StatsPullAtomService extends SystemService {
|
||||
pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag, managedProcess.uid,
|
||||
managedProcess.processName, managedProcess.pid, managedProcess.oomScore,
|
||||
snapshot.rssInKilobytes, snapshot.anonRssInKilobytes, snapshot.swapInKilobytes,
|
||||
snapshot.anonRssInKilobytes + snapshot.swapInKilobytes));
|
||||
snapshot.anonRssInKilobytes + snapshot.swapInKilobytes,
|
||||
gpuMemPerPid.get(managedProcess.pid)));
|
||||
}
|
||||
// Complement the data with native system processes. Given these measurements can be taken
|
||||
// in response to LMKs happening, we want to first collect the managed app stats (to
|
||||
@@ -2248,7 +2253,8 @@ public class StatsPullAtomService extends SystemService {
|
||||
processCmdlines.valueAt(i), pid,
|
||||
-1001 /*Placeholder for native processes, OOM_SCORE_ADJ_MIN - 1.*/,
|
||||
snapshot.rssInKilobytes, snapshot.anonRssInKilobytes, snapshot.swapInKilobytes,
|
||||
snapshot.anonRssInKilobytes + snapshot.swapInKilobytes));
|
||||
snapshot.anonRssInKilobytes + snapshot.swapInKilobytes,
|
||||
gpuMemPerPid.get(pid)));
|
||||
}
|
||||
return StatsManager.PULL_SUCCESS;
|
||||
}
|
||||
@@ -2328,7 +2334,8 @@ public class StatsPullAtomService extends SystemService {
|
||||
if (process.uid == Process.SYSTEM_UID) {
|
||||
continue;
|
||||
}
|
||||
DmabufInfoReader.ProcessDmabuf proc = DmabufInfoReader.getProcessStats(process.pid);
|
||||
KernelAllocationStats.ProcessDmabuf proc =
|
||||
KernelAllocationStats.getDmabufAllocations(process.pid);
|
||||
if (proc == null || (proc.retainedBuffersCount <= 0 && proc.mappedBuffersCount <= 0)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user