当前位置:首页>Linux>Linux cpu 性能分析(3):火焰图(Flame Graph)—— 从 CPU 到“万物皆可火焰图”

Linux cpu 性能分析(3):火焰图(Flame Graph)—— 从 CPU 到“万物皆可火焰图”

  • 2026-10-11 06:31:58
Linux cpu 性能分析(3):火焰图(Flame Graph)—— 从 CPU 到“万物皆可火焰图”

Linux cpu 性能分析(3):火焰图(Flame Graph)—— 从 CPU 到“万物皆可火焰图”

在 Linux 性能分析领域,Flame Graph(火焰图) 已经成为定位性能瓶颈最重要的可视化工具之一。无论是 CPU 使用率过高、线程阻塞、锁竞争、磁盘 IO,还是 Page Fault、网络延迟,都可以通过火焰图直观地展示。

很多初学者认为火焰图只能分析 CPU,其实这是一个误区。火焰图本质上是一种可视化方式,而不是一种采样方法。 任何能够采集到调用栈(Stack Trace)的事件,都可以生成对应的火焰图,因此业内也流传着一句话:

Anything can be a Flame Graph(万物皆可火焰图)。

本文介绍几种最常见的火焰图类型,以及它们适用的分析场景。

什么是火焰图?

火焰图由 Brendan Gregg 提出,它将大量调用栈按照相同路径进行聚合,并以矩形的形式展示。

一张典型的 CPU 火焰图如下:

main

│

┌───────┴────────┐

nginxworker

││

process()handle_req()

││

parse()mysql_query()

││

memcpy()send()

火焰图有两个重要特点:

横轴(Width)

表示资源消耗。

对于 CPU 火焰图:

矩形越宽,表示 CPU 时间越多。

注意:

横轴不是时间轴!

很多人第一次看火焰图都会误认为:

左边

──────►

右边

表示程序执行时间,这是错误的。

横轴只是把相同调用栈合并后的统计结果。

纵轴(Height)

表示调用关系。

例如:

main()

└── foo()

└──bar()

└──memcpy()

最底层是入口函数。

越往上调用越深。

On-CPU Flame Graph(CPU 火焰图)

这是最经典的火焰图, 也是人们最常用的。可以通过perf/profile生成

采样对象:

CPU 正在执行什么?

采样来源:

●perf

●profile(BCC)

●eBPF profile

例如:

main

├── parser

│└── json_parse

│

└── worker

└──memcpy

如果:

memcpy

特别宽。

说明:

CPU 大部分时间花在 memcpy。

适用于:

●CPU 使用率高

●查找热点函数

●性能 Profiling

Off-CPU Flame Graph(阻塞火焰图)

CPU 火焰图只能回答:

CPU 在忙什么?

但是:

CPU 利用率很低,

程序为什么还是很慢?

这时候就需要:

Off-CPU Flame Graph (bcc工具offcputime)

采样:

线程什么时候睡眠?

例如:

read()

futex()

poll()

epoll_wait()

这些函数越宽,

说明等待时间越长。 

典型问题:

●IO 等待

●锁竞争

●数据库等待

●网络等待

很多线上问题:

CPU 只有 20%

但响应时间很长。

最后发现:

全部卡在:

futex()

就是 Off-CPU 找出来的。

Wakeup Flame Graph(唤醒火焰图)

线程为什么被唤醒?可以使用bcc工具wakeuptime

例如:

Thread A

│

▼

pthread_cond_signal()

唤醒

Thread B

Wakeup Flame Graph

统计:

是谁唤醒了别人?

适用于:

●调度分析

●锁竞争

●Producer / Consumer

例如:

Java、

Kafka、

Redis、

数据库

大量线程唤醒。 

Off-Wakeup Flame Graph

Wakeup 看:

谁唤醒别人。

Off-Wakeup:通过bcc工具offwaketime

看:

谁让别人睡觉。

例如:

Thread A

↓

pthread_mutex_lock()

↓ 

Thread B

↓

pthread_mutex_unlock()

Off-Wakeup 可以分析:

阻塞是谁造成的。

它非常适合:

分析锁竞争。

Page Fault Flame Graph

可以使用工具perf指定event(-e ), 以及关联的调用函数栈(-g)

sudoperf record \

-epage-faults \

-g\

-ppid

Page Fault

不仅影响内存。

也影响 CPU。

例如:

malloc()

↓ 

缺页

↓

Page Fault

↓

Kernel

↓ 

分配物理页

Page Fault Flame Graph

可以统计:

哪些函数

最容易触发:

●Minor Fault

●Major Fault

例如:

数据库

Redis

JVM

内存映射文件。

Memory Flame Graph

可以使用bpftrace关联uprobe以及对应的调用栈

bpftrace -e '

uprobe:/lib/x86_64-linux-gnu/libc.so.6:malloc

{

@[ustack]= count();

}'

统计:

malloc

free

new

delete

例如:

operator new()

↓

std::vector

↓ 

push_back()

可以找到:

内存分配热点。

为什么说“万物皆可火焰图”?

火焰图并不是 CPU 专属工具,而是一种调用栈聚合与可视化技术。

只要能够获取事件发生时的调用栈(Call Stack),就可以按照相同的方法生成火焰图。因此,火焰图不仅适用于 CPU,还可以用于内存、I/O、锁、中断、调度等各种场景。

例如:

可以看到,它们唯一的区别只是采样事件不同(perf/bcc/bpftrace)

●CPU Samples → On-CPU Flame Graph

●Sleep Event → Off-CPU Flame Graph

●Wakeup Event → Wakeup Flame Graph

●Page Fault Event → Page Fault Flame Graph

而最终都采用相同的火焰图形式进行展示

总结

火焰图不是一种性能分析工具,而是一种调用栈聚合与可视化方法。它的核心思想是:把海量事件按照调用路径进行聚合,并用矩形宽度表示资源消耗或事件发生频率。

在现代 Linux 性能分析中,CPU 火焰图只是最常见的一种形式。随着 eBPF、perf、BCC、bpftrace 等技术的发展,几乎所有能够获取调用栈的事件都可以生成火焰图。因此,从 CPU、内存、调度、锁竞争,到网络、文件系统、中断甚至系统调用,都可以用同一种方式进行分析,这也是性能分析领域广为流传的理念——“万物皆可火焰图(Anything can be a Flame Graph)”。

最新文章

随机文章