你好,我是风一样的树懒,一个工作十多年的后端开发,曾就职京东、阿里等多家互联网头部企业。
文章可能会比较长,主要解析的非常详解,或涉及一些底层知识,供面试高阶难度用。可以根据自己实际理解情况合理取舍阅读
通过 定时采样 记录程序调用栈,统计各函数在采样中的出现频率
X轴:采样数量(越宽表示消耗越多CPU时间)
Y轴:调用栈深度(上层函数调用下层函数)
颜色:通常无特定含义,用于区分不同调用链
# 安装perf和FlameGraph工具集
sudo apt-get install linux-tools-common linux-tools-generic
git clone https://github.com/brendangregg/FlameGraph.git
# 对进程进行采样(30秒)
sudo perf record -F 99 -p <PID> -g -- sleep 30
# 生成原始数据文件
sudo perf script > perf.data.out
# 转换数据格式
FlameGraph/stackcollapse-perf.pl perf.data.out > perf.folded
# 生成SVG图形
FlameGraph/flamegraph.pl perf.folded > flame.svg
# 下载工具
wget https://github.com/jvm-profiling-tools/async-profiler/releases/download/v2.9/async-profiler-2.9-linux-x64.tar.gz
# 生成CPU火焰图
./profiler.sh -d 30 -f /tmp/flame.svg <PID>
# 内存分配火焰图
./profiler.sh -e alloc -d 60 -f alloc.svg <PID>
# 启动Arthas后执行
profiler start # 开始采样
profiler stop --format flamegraph > /tmp/flame.html # 生成HTML格式
图形特征 | 问题类型 | 解决方案 |
平顶山 | 单一函数高消耗 | 优化热点函数算法 |
长条形阶梯 | 深层调用链 | 检查是否存在冗余调用 |
锯齿状边缘 | 频繁短时函数调用 | 考虑批量处理或缓存机制 |
点击放大:查看具体函数调用细节
搜索框:按函数名过滤关键路径(如输入java过滤JVM内部调用)
./profiler.sh -d 60 -f hotspot.svg 1234
2.代码优化
该函数内部存在正则表达式回溯问题
优化正则表达式为^[A-Z0-9]{8}$,CPU下降至40%
./profiler.sh -d 30 -f base.svg <PID>
./profiler.sh -d 30 -f new.svg <PID>
difffolded.pl base.svg new.svg | flamegraph.pl > diff.svg
# 跟踪内存分配
./profiler.sh -e alloc -d 300 -f alloc.svg <PID>
1.采样时间:生产环境建议至少采样30秒(避免偶然性)
2.符号表:确保保留调试符号(Java需保留-g编译参数)
3.容器环境:需挂载/sys/kernel/debug并开启perf_event_open
4.安全权限:部分操作需要CAP_PERFMON或root权限
通过火焰图可以快速定位以下典型问题:
代码热点:消耗大量CPU的函数
锁竞争:显示在monitorenter/park()的堆积
IO瓶颈:在read/write系统调用处出现宽条
内存问题:分配路径上出现异常高频调用
建议将火焰图生成流程封装为监控系统的自动诊断模块,实现:
告警触发 -> 自动采样 -> 图形生成 -> 归档分析 的完整闭环。
今天的内容就分享到这儿,喜欢的朋友可以关注,点赞。有什么不足的地方欢迎留言指出,您的关注是我前进的动力!