一、内存使用占比计算
内存使用占比(Memory Usage Percentage)可以通过不同的方式计算,具体取决于您想要衡量的是哪种类型的内存使用情况。以下是几种常见的计算方法:
-
基于MemTotal和MemFree:
- 公式 : <math xmlns="http://www.w3.org/1998/Math/MathML"> Memory Usage Percentage = ( 1 − MemFree MemTotal ) × 100 % \text{Memory Usage Percentage} = \left(1 - \frac{\text{MemFree}}{\text{MemTotal}}\right) \times 100\% </math>Memory Usage Percentage=(1−MemTotalMemFree)×100%
- 说明 :此公式仅考虑了空闲内存(
MemFree
),没有考虑到缓存或缓冲区等其他因素。
-
基于MemTotal和MemAvailable:
- 公式 : <math xmlns="http://www.w3.org/1998/Math/MathML"> Memory Usage Percentage = ( 1 − MemAvailable MemTotal ) × 100 % \text{Memory Usage Percentage} = \left(1 - \frac{\text{MemAvailable}}{\text{MemTotal}}\right) \times 100\% </math>Memory Usage Percentage=(1−MemTotalMemAvailable)×100%
- 说明 :此公式考虑了系统可以使用的总内存(
MemAvailable
),包括空闲内存以及可立即释放的缓存和缓冲区。
-
基于MemTotal和实际使用的内存:
- 公式 : <math xmlns="http://www.w3.org/1998/Math/MathML"> Memory Usage Percentage = ( MemTotal − ( MemFree + Buffers + Cached ) MemTotal ) × 100 % \text{Memory Usage Percentage} = \left(\frac{\text{MemTotal} - (\text{MemFree} + \text{Buffers} + \text{Cached})}{\text{MemTotal}}\right) \times 100\% </math>Memory Usage Percentage=(MemTotalMemTotal−(MemFree+Buffers+Cached))×100%
- 说明 :此公式考虑了空闲内存(
MemFree
)、缓存(Cached
)和缓冲区(Buffers
),这些通常不计入实际使用的内存。
在Linux系统中,通常推荐使用基于MemAvailable
的计算方法,因为它提供了更接近实际可用内存的值。这种方法考虑到了操作系统缓存和缓冲区对可用内存的影响,而这些缓存和缓冲区在需要时可以被迅速释放给应用程序使用。
下面是一个具体的例子,假设我们有以下内存统计数据:
MemTotal
: 16GB (16384 MB)MemFree
: 2GB (2048 MB)MemAvailable
: 4GB (4096 MB)Buffers
: 1GB (1024 MB)Cached
: 2GB (2048 MB)
使用基于MemAvailable
的方法计算内存使用占比:
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> Memory Usage Percentage = ( 1 − 4096 16384 ) × 100 % = ( 1 − 1 4 ) × 100 % = 75 % \text{Memory Usage Percentage} = \left(1 - \frac{4096}{16384}\right) \times 100\% = \left(1 - \frac{1}{4}\right) \times 100\% = 75\% </math>Memory Usage Percentage=(1−163844096)×100%=(1−41)×100%=75%
因此,内存使用占比为75%。
二、实时内存占比
实时展示内存信息脚本:
show_mem.py
python
import subprocess
import time
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
def ensure_root():
try:
subprocess.run(["adb", "root"], check=True)
print("Root permission granted.")
except subprocess.CalledProcessError as e:
print("Failed to get root permission, the script may not work correctly:", e)
def get_memory_info():
try:
cmd = "adb shell cat /proc/meminfo"
result = subprocess.run(cmd, shell=True, text=True, capture_output=True)
meminfo = result.stdout.splitlines()
mem_total = int(next(line for line in meminfo if line.startswith('MemTotal:')).split()[1])
mem_free = int(next(line for line in meminfo if line.startswith('MemFree:')).split()[1])
buffers = int(next(line for line in meminfo if line.startswith('Buffers:')).split()[1])
cached = int(next(line for line in meminfo if line.startswith('Cached:')).split()[1])
mem_used = mem_total - (mem_free + buffers + cached)
mem_usage_percent = (mem_used / mem_total) * 100
return mem_usage_percent
except Exception as e:
print("Error retrieving memory info:", e)
return None
# 初始化图表
fig, ax = plt.subplots()
xdata, ydata = [], []
ln, = plt.plot(xdata, ydata, 'r-')
# 初始化文本标签
txt_mem_usage = ax.text(0.5, 0.9, '', transform=ax.transAxes, ha='center')
def init():
ax.set_xlim(0, 60) # 初始化x轴显示60秒数据
ax.set_ylim(0, 100) # 内存使用率在0%到100%之间
ax.set_xlabel('Time (seconds)')
ax.set_ylabel('Memory Usage (%)')
ax.set_title('Memory Usage - Real-time')
return ln,
def update(frame):
mem_usage = get_memory_info()
if mem_usage is not None:
xdata.append(frame)
ydata.append(mem_usage)
# 更新图表数据
ln.set_data(xdata, ydata)
txt_mem_usage.set_text(f'Memory Usage: {mem_usage:.2f}%')
# 动态更新x轴范围,始终显示最近的60秒数据
ax.set_xlim(max(xdata[0] - 1, frame - 60), frame + 1)
# 重新绘制图表
fig.canvas.draw()
else:
txt_mem_usage.set_text('Failed to retrieve memory information')
return ln, txt_mem_usage,
ensure_root() # 在脚本开始的地方调用确保root权限的函数
# 创建动画
ani = FuncAnimation(fig, update, frames=range(1000),
init_func=init, blit=True, interval=1000)
plt.show()
三、历史内存占比
保存内存信息可执行文件代码:
mem_collect.c
c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#define MEMINFO_PATH "/proc/meminfo"
#define OUTPUT_FILE "/data/memory_info.txt"
#define SLEEP_TIME 5 // 每秒执行一次
// 定义要保存的字段
const char* fields_to_save[] = {
"MemTotal",
"MemFree",
"MemAvailable",
"Buffers",
"Cached"
};
const size_t fields_count = sizeof(fields_to_save) / sizeof(fields_to_save[0]);
void save_memory_info_with_timestamp() {
FILE *fp = fopen(OUTPUT_FILE, "a"); // 追加模式打开文件
if (fp == NULL) {
perror("Error opening output file");
return;
}
FILE *meminfo_file = fopen(MEMINFO_PATH, "r");
if (meminfo_file == NULL) {
perror("Error opening meminfo file");
fclose(fp);
return;
}
char buffer[1024];
char *line, *field;
float value;
time_t now = time(NULL);
struct tm *local_time = localtime(&now);
// 格式化时间戳
fprintf(fp, "Time: %d-%02d-%02d %02d:%02d:%02d -\t",
local_time->tm_year + 1900, local_time->tm_mon + 1, local_time->tm_mday,
local_time->tm_hour, local_time->tm_min, local_time->tm_sec);
for (size_t i = 0; i < fields_count; ++i) {
rewind(meminfo_file); // 重置文件指针到文件开头
while (fgets(buffer, sizeof(buffer), meminfo_file)) {
if (strstr(buffer, fields_to_save[i])) {
field = strtok(buffer, ":");
field = strtok(NULL, ":"); // 跳过字段名,获取数值
value = atof(field);
fprintf(fp, "%s: %f kB\t", fields_to_save[i], value);
break;
}
}
}
fprintf(fp, "\n"); // 每个时间戳后添加一个空行
fclose(meminfo_file);
fclose(fp);
}
int main() {
system("rm -rf /data/memory_info.txt");
while (1) {
save_memory_info_with_timestamp();
sleep(SLEEP_TIME);
}
return 0;
}
- 将mem_collect.c放在Android源码环境下编译,或者配置Android ndk交叉编译环境
- 编译完成后将可执行文件push到机器中/system/bin/下(push前adb root && adb remount)
- 执行mem_collect保存机器内存信息,保存文件路径:/data/memory_info.txt
解析memory_info.txt脚本:
mem_parser.py
python
import matplotlib.pyplot as plt
import datetime
# 定义一个函数来解析每一行的数据
def parse_line(line):
parts = line.strip().split()
timestamp_str = parts[1] + ' ' + parts[2]
mem_info = {}
for i, part in enumerate(parts):
if part.endswith(':'):
key = part[:-1] # 去掉冒号
if key in ['MemTotal', 'MemFree', 'MemAvailable', 'Buffers', 'Cached']:
value = float(parts[i+1].replace('kB', '')) # 去掉'kB'后缀
mem_info[key] = value
# 计算内存使用百分比
if 'MemTotal' in mem_info and 'MemAvailable' in mem_info:
mem_used_percent = (mem_info['MemTotal'] - mem_info['MemAvailable']) / mem_info['MemTotal'] * 100
else:
raise ValueError("Could not find total or available memory values.")
return timestamp_str, mem_used_percent
# 读取文件并解析每一行数据
timestamps = []
mem_used_percentages = []
with open('D:\python\memory_info.txt', 'r') as file:
for line in file:
if line.startswith('Time:'):
timestamp, mem_used_percent = parse_line(line)
timestamps.append(datetime.datetime.strptime(timestamp, '%Y-%m-%d %H:%M:%S'))
mem_used_percentages.append(mem_used_percent)
# 绘制图表
plt.figure(figsize=(10, 5))
plt.ylim(0, 100)
plt.plot(timestamps, mem_used_percentages, marker='o')
plt.title('Memory Usage Over Time')
plt.xlabel('Timestamp')
plt.ylabel('Memory Used (%)')
plt.grid(True)
plt.xticks(rotation=45)
plt.tight_layout() # 自动调整子图参数,使之填充整个图像区域
plt.show()
运行环境: Ubuntu 20.04.6 LTS、 Windows 10、 Python 3.11.3