七张图看懂 Linux profiling 机制
1 图 1 Linux profiling 手段一览
软件埋点:
- 手动埋点:主动调用 trace 函数来实现埋点。
Android systrace 即是这样一个例子,如图 2 和 图 3 所示 - 自动埋点:借助工具链,自动埋点,对函数的 entry 和 return 进行 hook。
Linux ftrace 即是这样一个例子,图 4 简示了其实现原理 - 动态埋点:运行时刻,在指定位置上加断点,断点触发时执行相应 handler。
Handler 为注入内核的 eBPF 字节码
Linux kprobe / uprobe 就是这样的例子,图 5 和 图 6 简示了 uprobe 以及 uretprobe 的实现原理
- 手动埋点:主动调用 trace 函数来实现埋点。
硬件统计
- 计数累加:统计一段时间内,某个性能监控单元(PMU)的计数。
例如:perf stat -e cache-misses -p PID
,参见 brendangregg.com/perf.html ,Counting Events 一节
函数接口:参见 libperf 的封装,fd = perf_event_open(...); read(fd, …) - 采样:计数达标,产生中断,伴随 Backtrace 对应到代码行。
例如:perf record -F 99 -p PID sleep 10
,以及对应图形化展示 FlameGraph
函数接口:参见perf_event_open,fd = perf_event_open(…); void *addr = mmap(…, fd, …);
图 7 简示了其实现原理
- 计数累加:统计一段时间内,某个性能监控单元(PMU)的计数。
2 图 2 Android systrace 工作原理
User space,分为两部分
- 埋点处:通过嵌入代码中的 Trace API 调用,向 Linux kernel 的 tracing buffer 写日志。
上图中,裸示了写 tracing buffer 的过程 - atrace:读取 tracing buffer,存于磁盘文件,以免 tracing buffer 溢出丢失信息。
- 埋点处:通过嵌入代码中的 Trace API 调用,向 Linux kernel 的 tracing buffer 写日志。
Kernel space,通过 scheduler 嵌入的 tracepoint,将调度事件,写入 tracing buffer。
tracing buffer 犹如一段 in-memory 的日志流,对齐了写入的各个标记和事件。
3 图 3 Android atrace 输出文件及图形化展示
atrace 转储的 tracing buffer 内容,以及载入到 Chrome 浏览器,进行图形化分析。
Discuss:想象一个进程同时播放两段视频,视频解码库是多线程的,线程来自全局的 thread pool。通过 systrace,能区分这两个视频播放任务的 CPU 时间片吗?
4 图 4 Linux ftrace 实现原理回顾
- 通过 gcc -pg 选项,编译时,函数开头自动插入 _mcount 调用。
- _mcount 处:除了 hook entry ,还通过修改返回地址,来 hook return。
Linux kernel 热补丁方案,”kernel livepatch“,便借用了 ftrace 的原理:替换有漏洞的函数实现,从而实现热补丁。
更多关于 ftrace 使用,参考「Advanced Features of Ftrace」
5 图 5 uprobe 的实现原理
注:上图修改自 dev.framing.life/tracing/kernel-and-user-probes-magic
指定位置上的指令,头部修改为软件中断指令(同时原指令存档他处):
- 当执行到该位置时,触发软件中断,陷入内核
- 在内核,执行以 eBPF 字节码形式注入的 Handler
- 单步执行原指令
- 修正寄存器和栈,回到原有指令流
Discuss:这与 gdb 中设断点有什么区别?
断点的 Handler 运行于 Kernel space,无需多次的 User space Kernel space 通信
Discuss:用户空间注入的 Handler 在 Kernel space 执行,安全性如何保证?
听说过 eBPF 吗?
简单介绍下 extended Berkeley Packet Filter(eBPF)
- 一种功能有限、沙箱化的字节码。
- 由 User space 注入到 Kernel space 执行。
- 基于 BPF 扩展。
原始的 BPF 用于网路包过滤,下面是一个 BPF 裸用的例子:
/**
* 通过 netlink socket,获得关心进程的消亡信息
*/
int sock_fd = socket (PF_NETLINK, SOCK_DGRAM | SOCK_NONBLOCK | SOCK_CLOEXEC, NETLINK_CONNECTOR);
union {
struct sockaddr sa;
struct sockaddr_nl nl;
} addr = { .nl.nl_family = AF_NETLINK, .nl.nl_pid = getpid(), .nl.nl_groups = CN_IDX_PROC };
enum proc_cn_mcast_op op = PROC_CN_MCAST_LISTEN;
struct cn_msg cn_msg = { .id.idx = CN_IDX_PROC, .id.val = CN_VAL_PROC, .len = sizeof(op) };
struct iovec iov[3] = {
[0] = { .iov_base = nlmsghdrbuf, .iov_len = NLMSG_LENGTH(0) },
[1] = { .iov_base = &cn_msg, .iov_len = sizeof(cn_msg) },
[2] = { .iov_base = &op, .iov_len = sizeof(op) }
};
bind(sock_fd, &addr.sa, sizeof(addr.nl));
/* start proc connector */
writev (sock_fd, iov, 3);
/* 借助 BPF,从 Process Events 中,滤出「进程消亡事件」 */
struct sock_filter filter[] = {
...
/* 6-7: filter out proc connector message other than 'PROC_EVENT_EXIT' */
BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
NLMSG_LENGTH(0) + offsetof(struct cn_msg, data)
+ offsetof(struct proc_event, what)),
BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K,
htonl(PROC_EVENT_EXIT), 0 /* true offset */, 1 /* false offset */),
/* 8: the @ret_cmd_idx */
BPF_STMT (BPF_RET|BPF_K, 0xffffffff),
/* 9: the @drop_cmd_idx */
BPF_STMT (BPF_RET|BPF_K, 0)
};
struct sock_fprog fprog = { .filter = filter, .len = 10 };
setsockopt (sock_fd, SOL_SOCKET, SO_ATTACH_FILTER, &fprog, sizeof (fprog)) < 0)
eBPF 形式上类似,裸用相当不方便,好在有编译器 bcc,以及高级语言 bpftrace。
6 图 6 uretprobe 工作原理
图 5 展示的是 User level 埋点,故而叫做 uprobe。Kernel level 对应款叫做 kprobe。
uprobe 和 kprobe 的通常用法中,以函数入口地址,进行埋点。而对于函数返回,其位置可能有多处:
int foo(..) {
size_t n_written = 0;
if (cond1) return -EINVAL;
if (cond2) goto fail;
n_written = do_io(...);
return n_written;
fail:
free(...); return -EIO;
}
于是就有了 kretprobe 以及 uretprobe。下图展示了 uretprobe 工作原理,同样修改自dev.framing.life/tracing/kernel-and-user-probes-magic
uprobe 的工作流中,需要指定位置方能埋点。除了上述提及的函数 entry & return,在函数中间某处埋点,意味着要反汇编,找到源代码行对应汇编地址,有些反人类。
于是,可以预先在代码中埋“标记”,再通过 uprobe 找到“标记”,进行埋点 —— USDT(User Statically-Defined Tracing) 就是这样一个技术,其实现简介参见这个链接。
节末,再提一个 uprobe 应用 “malloc() Flame Graph” ,通过埋点 malloc() / free() 来剖析目标进程的内存使用情况,分析是否存在泄漏。
7 图 7 性能计数采样工作原理
云上: 服务端程序需要扛住超高的并发请求;手机上:需要有效降低延时;计算密集型的神经网络中:GPU 需要极致优化的 kernel。
借助诸如硬件性能监控单元(PMU),可以统计高速硬件上的各种 “塞车” 事件,指出程序为何跑的慢。进一步对其采样,还可将 “塞车事件”,对应到造成 “塞车” 的热点代码行上。
“Cache Line 伪共享发现与优化“一文,介绍了如何发现名为 “Cache Line 伪共享” 的 “塞车事件”,并对应到代码行上。
下图简示了采样的工作原理:当 “塞车” 计数达到采样频率时,产生一次中断,转储现场,从而回溯到代码行和相关上下文。
七张图看懂 Linux profiling 机制的更多相关文章
- 一张图看懂开源许可协议,开源许可证GPL、BSD、MIT、Mozilla、Apache和LGPL的区别
一张图看懂开源许可协议,开源许可证GPL.BSD.MIT.Mozilla.Apache和LGPL的区别 首先借用有心人士的一张相当直观清晰的图来划分各种协议:开源许可证GPL.BSD.MIT.Mozi ...
- [转帖]两张图看懂GDT、GDTR、LDT、LDTR的关系
两张图看懂GDT.GDTR.LDT.LDTR的关系 2018-06-09 18:13:53 Six_666A 阅读数 2044更多 分类专栏: 深入理解linux内核 转自:http://ju.o ...
- 一张图看懂ANSYS17.0 流体 新功能与改进
一张图看懂ANSYS17.0 流体 新功能与改进 提交 我的留言 加载中 已留言 一张图看懂ANSYS17.0 流体 新功能与改进 原创2016-02-03ANSYS模拟在线模拟在线 模拟在线 ...
- FUNMVP:几张图看懂区块链技术到底是什么?(转载)
几张图看懂区块链技术到底是什么? 本文转载自:http://www.cnblogs.com/behindman/p/8873191.html “区块链”的概念可以说是异常火爆,好像互联网金融峰会上没人 ...
- 4张图看懂delphi 10生成ipa和在iPhone虚拟器上调试(教程)
4张图看懂delphi 10生成ipa和在iPhone虚拟器上调试(教程) (2016-02-01 03:21:06) 转载▼ 标签: delphi ios delphi10 教程 编程 分类: 编程 ...
- 一张图看懂css的position里的relative和absolute的区别
position有以下属性:static.inherit.fixed.absolute.relative前三个好理解好区分:static:是默认状态,没有定位,元素出现在正常的流中(忽略 top, b ...
- 一张图看懂Function和Object的关系及简述instanceof运算符
我在写一篇图解prototype和__proto__的区别时,搜资料搜到了一个有意思的现象,下面这两个运算返回的结果是一样的: Function instanceof Object;//true Ob ...
- Nodejs学习笔记(三)——一张图看懂Nodejs建站
前言:一条线,竖着放,如果做不到精进至深,那就旋转90°,至少也图个幅度宽广. 通俗解释上面的胡言乱语:还没学会爬,就学起走了?! 继上篇<Nodejs学习笔记(二)——Eclipse中运行调试 ...
- 一张图看懂Rxjava的原理
前言 Rxjava是NetFlix出品的Java框架, 官方描述为 a library for composing asynchronous and event-based programs usin ...
- 12 张图看懂 CPU 缓存一致性与 MESI 协议,真的一致吗?
本文已收录到 GitHub · AndroidFamily,有 Android 进阶知识体系,欢迎 Star.技术和职场问题,请关注公众号 [彭旭锐] 进 Android 面试交流群. 前言 大家好 ...
随机推荐
- DP进阶合集
(ps:本集合为Star_F总结的dp进阶知识,持续更新~. 转载本文章需要联系我,否则视为侵权!!) 前置知识:线性dp,背包,树形dp,区间dp 内容预览: 状压dp 数位dp dp优化(前缀和, ...
- Bond4配置
Bongding聚合链路工作模式 > bond聚合链路模式共7种:0-6Mode > bond 0 负载均衡 轮询方式往每条链路发送报文,增加带宽和容错能力.容易出现数据包无序到达的问题, ...
- ios的idp/iep证书的生成方法,无苹果电脑
在这个多端开发的年代,出现了很多优秀的开发框架,比如hbuilder和uniapp等等.我们可以使用这些框架来开发APP,假如我们要打包ios的app,则需要一个idp/iep证书. 那么这个证书是如 ...
- perf 性能分析工具
perf 性能分析工具 perf topperf recordperf reportperf listperf stat perf top -p <pid> 例如查看redis进程的内核调 ...
- 【Git】介绍与概述
版本控制工具应该具备的功能? 协同修改 多人并行不悖的修改服务器端的同一个文件. 数据备份 不仅保存目录和文件的当前状态,还能够保存每一个提交过的历史状态. 版本管理 在保存每一个版本的文件信息的时候 ...
- 【Docker】10 容器存储
将容器保存为一个镜像: docker commit 容器的名称 创建的镜像的名称 将镜像保存为一个tar包文件: docker save -o tar包文件名称.tar 镜像名称 可以看到Docker ...
- jdk命令行工具系列——检视阅读
jdk命令行工具系列--检视阅读 参考 java虚拟机系列 RednaxelaFX知乎问答 RednaxelaFX博客 jps--虚拟机进程状态工具 jps :(JVM Process Status ...
- 斯坦福AI团队被质疑抄袭国产大模型
原文地址: https://mbd.baidu.com/newspage/data/landingsuper?context={"nid"%3A"news_8882699 ...
- jax框架为例:求hession矩阵时前后向模式的自动求导的性能差别
注意:本文相关基础知识不介绍. 给出代码: from jax import jacfwd, jacrev import jax.numpy as jnp def hessian_1(f): retur ...
- 讲师招募 | Apache DolphinScheduler Meetup诚邀您共建开源!
随着Apache DolphinScheduler在全球范围内的快速发展,我们的用户群体和社区活动也在不断扩大. 为了进一步丰富我们的社区内容,分享更多有价值的知识和经验,我们诚挚地邀请您加入我们,成 ...