A10 — Memory Analysis Tools: malloc_stats, Valgrind Massif, pmap
Key Insight: The first step to optimizing memory is knowing where it is being used.
malloc_stats: glibc Allocation Statistics
malloc_stats() 输出所有 arena 的统计信息:
#include <malloc.h>
malloc_stats();
输出示例:
Arena 0:
system bytes = 1048576
memory bytes = 1048576
96 malloc-chunks in use (12345 bytes)
Arena 1:
system bytes = 2097152
...
字段解释:
system bytes:从系统获取的总内存
memory bytes:实际使用的内存
96 malloc-chunks:正在使用的块数
12345 bytes:正在使用的字节数
实时查看:
#include <mcheck.h>
mtrace(); // 开启 malloc 跟踪
// 运行程序后
// MALLOC_TRACE=/tmp/trace ./program
// mtrace ./program /tmp/tracemallinfo:结构化的分配信息:
#include <malloc.h>
struct mallinfo mi = mallinfo();
mi.arena:所有 arena 的总大小
mi.ordblks:空闲块数
mi.hblks:mmap 分配的大块数
mi.hblkhd:mmap 分配的总字节数
mi.uordblks:正在使用的字节数
mi.fordblks:空闲字节数
mi.keepcost:top chunk 的大小(可释放)
使用示例:
struct mallinfo mi = mallinfo();
printf("使用中: %d bytesn", mi.uordblks);
printf("空闲: %d bytesn", mi.fordblks);
printf("mmap 大块: %d bytesn", mi.hblkhd);Valgrind Massif: Heap Profiler
valgrind --tool=massif ./program
生成 snapshot 文件:massif.out.12345
分析工具 ms_print:
$ ms_print massif.out.12345
GB
1.972^ #
| ####
| ### #
| ### ##
| ### ##
| ### #
| ### #
| ### #
| ### #
| ### #
| ### #
0 +-------------------------------------------#------->GB
0 50 100 150 200 250 300
Snapshot 100 (MB)
堆峰值:1.972 GB(发生在 250s)
堆详细分配(Snapshot 100):
0x40000000: 0x100000 (1024KB) 0x... (malloc)
...
ms_print 输出:
- 每列 = 一个 snapshot(时间序列)
- 每个 snapshot 显示堆使用量
- 峰值在哪里(Peak)
- 详细堆栈(包含分配位置)ms_print 的内容解读:
Snapshot 50 details:
n0 "main" malloc @ 0x400567
0x400567: allocate 1024 bytes (test.c:10)
0x400789: func() (test.c:25)
0x400ABC: main (test.c:50)
字段:
n0:节点编号(堆快照中的编号)
"main":malloc 调用的函数栈
test.c:10:具体代码位置
1024 bytes:分配的大小
峰值信息:
Peak GB: 1.972 (在 Snapshot 200)
峰值占比:99% 来自 main() 中的某个循环pmap: Viewing Process Memory Mappings
pmap 查看进程的完整内存布局:
$ pmap -x 12345
12345: ./program
Address RSS Dirty Mode Mapping
00007f... 4 KB 4 KB r-xp [vsyscall]
00007f... 16384 KB 16384 KB rw-p [anon]
00007f... 4 KB 4 KB rw-p [stack]
00007f... 8192 KB 8192 KB rw-p [heap]
...
字段:
Address:虚拟地址范围
RSS:Resident Set Size(实际驻留内存)
Dirty:脏页数量
Mode:权限(r-xp=代码,rw-p=数据)
Mapping:映射类型(文件路径/[heap]/[stack]/[anon])
pmap -X(详细):
- 显示每个页的详细信息
- 更详细的内存统计pmap 查看泄漏:
$ pmap -x 12345 | sort -k3 -n -r | head -20
// 按 RSS 排序,找出内存占用最多的区域
00007f... 16384 KB ... [anon] ← 可能是泄漏(mmap 大块)
00007f... 8192 KB ... [heap] ← 堆(brk 管理)/proc/self/status and /proc/self/statm
/proc/self/status:
$ cat /proc/self/status
VmPeak: 123456 kB // 峰值虚拟内存
VmSize: 12345 kB // 当前虚拟内存
VmRSS: 8192 kB // 实际驻留内存
VmData: 4096 kB // 数据段大小(堆)
VmStk: 128 kB // 栈大小
VmSwap: 0 kB // 交换出去的大小
VmPeak 持续增长 = 内存泄漏的信号
---
/proc/self/statm:
$ cat /proc/self/statm
8192 4096 12345 0 0 1000 0
│ │ │ │ │ │ └── 0(未知)
│ │ │ │ │ └────── RSS pages
│ │ │ │ └────────── size pages(总虚拟)
│ │ │ └──────────── shared pages
│ │ └────────────────── text pages(代码)
│ └─────────────────────── resident pages
└──────────────────────────── total pages
字段:
total: 总虚拟页数
resident: 驻留页数
shared: 共享页数
text: 代码页数
data: 数据页数(堆+栈+数据)perf and Flame Graphs for Memory Analysis
perf record 跟踪内存访问:
$ perf record -g -e cycles:u ./program
$ perf report
输出:
- cycles:u:用户态 CPU 周期
- -g:记录调用栈
- 生成 report,分析热点
火焰图(FlameGraph):
$ perf record -g -e cycles:u ./program
$ perf script | ./stackcollapse-perf.pl | ./flamegraph.pl > flame.svg
火焰图:
- Y 轴 = 调用栈深度
- 方块宽度 = 执行时间
- 从下往上看,可以看到内存分配的热力图
分析内存热点:
- 哪些函数分配最多内存
- 哪些路径触发最多分配
- 优化热点,减少不必要的分配Summary
- malloc_stats(): Real-time output of all arena statistics (system/used/free bytes)
- mallinfo: Structured statistics (arena/ordblks/hblks/hblkhd/uordblks/fordblks)
- valgrind –tool=massif: Heap analysis; ms_print to view peaks and timeline; locate leaks
- pmap -x: View process virtual address mappings (RSS/permissions/type); sort by RSS to find top consumers
- /proc/self/status: VmPeak/VmRSS/VmData/VmSwap; sustained growth indicates a leak
- perf + Flame Graphs: Tracks CPU cycles; generates flame graphs; analyzes allocation hotspots
Next (A11): How do user space and kernel space memory interact? mmap, brk, and zero-copy principles.
Comments