blob: 30b6e688bab6588b80406f99d591229ea6069c73 [file] [log] [blame]
/*
* Copyright (C) 2020 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.
*/
package com.android.server.stats.pull;
import android.os.Debug;
/**
* Snapshots system-wide memory stats and computes unaccounted memory.
* Thread-safe.
*/
final class SystemMemoryUtil {
private SystemMemoryUtil() {}
static Metrics getMetrics() {
int totalIonKb = (int) Debug.getDmabufHeapTotalExportedKb();
int gpuTotalUsageKb = (int) Debug.getGpuTotalUsageKb();
int gpuPrivateAllocationsKb = (int) Debug.getGpuPrivateMemoryKb();
int dmaBufTotalExportedKb = (int) Debug.getDmabufTotalExportedKb();
long[] mInfos = new long[Debug.MEMINFO_COUNT];
Debug.getMemInfo(mInfos);
long kReclaimableKb = 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 (kReclaimableKb == 0) {
kReclaimableKb = mInfos[Debug.MEMINFO_SLAB_RECLAIMABLE];
}
long accountedKb = mInfos[Debug.MEMINFO_FREE]
+ mInfos[Debug.MEMINFO_ZRAM_TOTAL]
+ mInfos[Debug.MEMINFO_BUFFERS]
+ mInfos[Debug.MEMINFO_ACTIVE]
+ mInfos[Debug.MEMINFO_INACTIVE]
+ mInfos[Debug.MEMINFO_UNEVICTABLE]
+ mInfos[Debug.MEMINFO_SLAB_UNRECLAIMABLE]
+ kReclaimableKb
+ mInfos[Debug.MEMINFO_VM_ALLOC_USED]
+ mInfos[Debug.MEMINFO_PAGE_TABLES];
if (!Debug.isVmapStack()) {
// See b/146088882
accountedKb += mInfos[Debug.MEMINFO_KERNEL_STACK];
}
// If we can distinguish gpu private allocs it means the dmabuf metrics
// are supported already.
if (dmaBufTotalExportedKb >= 0 && gpuPrivateAllocationsKb >= 0) {
// If we can calculate the overlap between dma memory and gpu
// drivers we can do more accurate tracking. But this is only
// available on 5.4+ kernels.
accountedKb += dmaBufTotalExportedKb + gpuPrivateAllocationsKb;
} else {
// If we cannot distinguish, accept that we will double count the
// dma buffers also used by the gpu driver.
accountedKb += Math.max(0, gpuTotalUsageKb);
if (dmaBufTotalExportedKb >= 0) {
accountedKb += dmaBufTotalExportedKb;
} else if (totalIonKb >= 0) {
// ION is a subset of total exported dmabuf memory.
accountedKb += totalIonKb;
}
}
Metrics result = new Metrics();
result.unreclaimableSlabKb = (int) mInfos[Debug.MEMINFO_SLAB_UNRECLAIMABLE];
result.vmallocUsedKb = (int) mInfos[Debug.MEMINFO_VM_ALLOC_USED];
result.pageTablesKb = (int) mInfos[Debug.MEMINFO_PAGE_TABLES];
result.kernelStackKb = (int) mInfos[Debug.MEMINFO_KERNEL_STACK];
result.totalIonKb = totalIonKb;
result.gpuTotalUsageKb = gpuTotalUsageKb;
result.gpuPrivateAllocationsKb = gpuPrivateAllocationsKb;
result.dmaBufTotalExportedKb = dmaBufTotalExportedKb;
result.unaccountedKb = (int) (mInfos[Debug.MEMINFO_TOTAL] - accountedKb);
return result;
}
static final class Metrics {
public int unreclaimableSlabKb;
public int vmallocUsedKb;
public int pageTablesKb;
public int kernelStackKb;
public int totalIonKb;
public int gpuTotalUsageKb;
public int gpuPrivateAllocationsKb;
public int dmaBufTotalExportedKb;
public int unaccountedKb;
}
}