Linux 性能实战系列 - 附录 Valgrind介绍

Valgrind 是一个 动态二进制分析框架 ,本身像一个"平台",在它之上运行不同的 分析工具(tools)

其中最常用的三个工具就是:

  • Memcheck
  • Callgrind
  • Massif

它们的关系可以理解为:

复制代码
                Valgrind (框架)
                      │
     ┌────────────────┼────────────────┐
     │                │                │
  Memcheck         Callgrind         Massif
 (内存正确性)      (CPU性能分析)     (堆内存分析)

三者目标完全不同,只是运行在同一个框架上。


一、Memcheck:内存错误检测工具

Memcheck 是 Valgrind 最常用的工具 ,主要用于发现 内存使用错误

能检测的问题

1️⃣ 内存泄漏

复制代码
definitely lost: 1024 bytes

例如:

c 复制代码
char *p = malloc(100);

没有 free(p)


2️⃣ 未初始化内存使用

c 复制代码
int x;
printf("%d\n", x);

Memcheck 会报告:

复制代码
Conditional jump or move depends on uninitialised value

3️⃣ 越界访问

c 复制代码
int a[10];
a[10] = 5;

报告:

复制代码
Invalid write of size 4

4️⃣ Use-after-free

c 复制代码
free(p);
*p = 1;

原理(简化)

Memcheck 为程序维护两种 shadow memory:

复制代码
真实内存
   │
   ▼
shadow memory
 ├── addressability (是否可访问)
 └── definedness   (是否初始化)

每条指令都会被 动态插桩(instrumentation) 检查。


运行方式

bash 复制代码
valgrind --tool=memcheck ./app

二、Callgrind:CPU性能分析工具

Callgrind 用于 分析程序执行时 CPU 时间消耗在哪里

它记录:

  • 函数调用关系
  • 每个函数执行的指令数
  • 调用图

输出文件:

复制代码
callgrind.out.<pid>

可用工具可视化:

  • KCachegrind
  • QCachegrind

示例

bash 复制代码
valgrind --tool=callgrind ./app

结果:

复制代码
Function                 Instructions
--------------------------------------
main                     10,000
foo                      6,000
bar                      3,000

可视化调用关系:

复制代码
main
 ├── foo
 │     └── baz
 └── bar

特点

Callgrind 不测真实时间,而是统计:

复制代码
CPU instructions

所以适合:

  • 算法性能分析
  • 热点函数定位

三、Massif:堆内存使用分析

Massif 用于分析:

程序在运行过程中堆内存是如何增长的

也就是 memory profile


运行

bash 复制代码
valgrind --tool=massif ./app

输出:

复制代码
massif.out.<pid>

分析:

bash 复制代码
ms_print massif.out.<pid>

示例输出

复制代码
Heap usage

    MB
10.0|        ######
    |       #      #
 5.0|      #        #
    |     #          #
 0.0+----+----+----+---->
      t1   t2   t3   t4

表示:

复制代码
时间  → 内存变化

Massif 会告诉你

复制代码
Peak heap: 120MB

90MB allocated at:
   foo()
   bar()
   main()

也就是:

哪一段代码造成了最大内存占用


四、三者核心区别

工具 作用 分析对象 典型用途
Memcheck 内存错误检测 内存访问 查内存泄漏
Callgrind CPU性能分析 指令执行 找热点函数
Massif 堆内存分析 内存占用 分析内存增长

五、三者运行开销对比

Valgrind 最大问题是

工具 速度
Memcheck 20--50x 慢
Callgrind 10--30x 慢
Massif 5--20x 慢

原因:

Valgrind 会:

复制代码
CPU指令
 ↓
Valgrind IR
 ↓
插桩
 ↓
执行

属于 动态二进制翻译 (DBI)


六、一个完整调试流程(真实开发常见)

一个 C/C++ 项目常见的 Valgrind 使用流程:

第一步:找内存问题

复制代码
valgrind --tool=memcheck

解决:

  • memory leak
  • invalid read/write

第二步:分析性能热点

复制代码
valgrind --tool=callgrind

定位:

复制代码
最慢函数

第三步:分析内存峰值

复制代码
valgrind --tool=massif

定位:

复制代码
内存增长来源

七、三者在 Valgrind 内部的关系(架构)

Valgrind 架构:

复制代码
                Program
                   │
                   ▼
           Valgrind Core
     (Dynamic Binary Translation)
                   │
        ┌──────────┼──────────┐
        │          │          │
     Memcheck   Callgrind   Massif
   (memory)     (cpu)       (heap)

核心部分:

复制代码
VEX IR

所有工具都基于这个 IR 插桩。


八、一个很多人不知道的事实

很多人以为:

复制代码
Memcheck 可以分析内存占用

其实 不行

Memcheck 只做:

复制代码
memory correctness

而不是:

复制代码
memory profiling

所以:

需求 工具
查内存泄漏 Memcheck
查内存占用 Massif

九、一个非常实用的工具组合

Linux 内存分析常见组合:

工具 用途
Valgrind Memcheck 查错误
Valgrind Massif 查内存
perf 查 CPU
heaptrack 高级 heap profiler

其中:

Heaptrack

实际上是 Massif 的现代替代品

相关推荐
爱笑鱼几秒前
Android 系统启动机制(六):Zygote 创建 App 为什么走 Socket?哪些是源码事实,哪些是架构解释?
android·linux
2601_9622998812 分钟前
Linux下运行Python脚本
linux·python·ubuntu·脚本·命令
wdfk_prog15 分钟前
Docker 常用语法与命令:CLI、Dockerfile 与 Compose 速查
运维·docker·容器
Zenova EdgeOS17 分钟前
Linux eBPF 工业边缘性能观测实战
linux·服务器·网络
skywalk816337 分钟前
通过下载Ubuntu ova文件在Virtual Box快速安装ubuntu
linux·运维·ubuntu·virtualbox
姚不倒40 分钟前
HAProxy 系列(四):多中间件统一 VIP 入口 — 架构模式与最佳实践
运维·中间件·架构·haproxy
wuminyu1 小时前
JVM锁膨胀与Futex源码解析
java·linux·c语言·jvm·c++
happymade1 小时前
7000 台网络设备批量纳管 & 自动拓扑生成实战——MSRM3 完整操作流程与关键要点复盘
运维·服务器·网络·zabbix·grafana·msrm3
斑马1391 小时前
Linux软件编程学习笔记(十一)——HTTP协议
linux·笔记·学习
做萤石二次开发的哈哈1 小时前
萤石蓝海 AIoT 一站式工作台:海康LCD会议平板接入,多端大屏运维应用一站生成
运维·物联网·电脑·萤石开放平台·会议室管理·蓝海aiot一站式工作台·otap物模型