Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 54 additions & 27 deletions docs/zh/05-features/04-continuous-profiling/01-auto-profiling.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,36 +15,41 @@ permalink: /features/continuous-profiling/auto-profiling

支持的 eBPF Profiling 数据类型:

| 类型 | 支持语言/库 | 社区版 | 企业版 |
| --------- | ---------------- | ------ | ------ |
| on-cpu | Java | ✔ | ✔ |
| | C/C++ | ✔ | ✔ |
| | Rust | ✔ | ✔ |
| | Golang | ✔ | ✔ |
| | CUDA | ✔ | ✔ |
| | Lua | | ✔ |
| | Python `***` | | ✔ |
| off-cpu | Java | | ✔ |
| | C/C++ | | ✔ |
| | Rust | | ✔ |
| | Golang | | ✔ |
| | Python `***` | | ✔ |
| | CUDA | | ✔ |
| | Lua `*` | | ✔ |
| on-gpu | CUDA `*` | | ✔ |
| mem-alloc | Java `**` | | ✔ |
| | Rust | | ✔ |
| | Golang `*` | | ✔ |
| | Python `*` `***` | | ✔ |
| mem-inuse | Rust | | ✔ |
| hbm-alloc | CUDA `*` | | ✔ |
| hbm-inuse | CUDA `*` | | ✔ |
| rdma | C/C++ `*` | | ✔ |
| 类型 | 支持语言/库 | 社区版 | 企业版 |
| ---------- | ----------- | ------ | ------ |
| on-cpu | Java | ✔ | ✔ |
| | C/C++ | ✔ | ✔ |
| | Rust | ✔ | ✔ |
| | Golang | ✔ | ✔ |
| | CUDA | ✔ | ✔ |
| | Node.js/V8 | | ✔ |
| | PHP | | ✔ |
| | Lua | | ✔ |
| | Python | | ✔ |
| off-cpu | Java | | ✔ |
| | C/C++ | | ✔ |
| | Rust | | ✔ |
| | Golang | | ✔ |
| | CUDA | | ✔ |
| | Node.js/V8 | | ✔ |
| | PHP | | ✔ |
| | Python | | ✔ |
| on-gpu | CUDA `*` | | ✔ |
| mem-alloc | Java `**` | | ✔ |
| | Rust | | ✔ |
| | Golang `*` | | ✔ |
| | Python | | ✔ |
| mem-inuse | Rust | | ✔ |
| | Python | | ✔ |
| hbm-alloc | CUDA `*` | | ✔ |
| | Python(调用 CUDA) | | ✔ |
| hbm-inuse | CUDA `*` | | ✔ |
| | Python(调用 CUDA) | | ✔ |
| rdma | C/C++ `*` | | ✔ |

说明:
- `*`: features in development
- `**`: 运行 Java 程序的 JVM 须有符号表,参考[检查方法](#jvm-符号表检查)
- `***`: 当前支持版本为 Python 3.10
- 类型:
- on-cpu:函数在 CPU 上消耗的时间
- off-cpu:函数等待 CPU 的时间
Expand All @@ -56,7 +61,29 @@ permalink: /features/continuous-profiling/auto-profiling
- 语言:
- 编译为 ELF 格式可执行文件的语言:Golang、Rust、C/C++
- 使用 JVM 虚拟机的语言:Java
- 解释型语言:Python
- 解释器运行时:Node.js/V8、PHP、Lua、Python

### 解释器运行时

解释器脚本函数栈展开属于企业版能力,当前支持范围如下:

| 运行时 | 支持版本 | 支持架构 | Profile 类型 |
| ------ | -------- | -------- | ------------ |
| Node.js/V8 | Node.js 16~23(V8 9~12) | x86_64、AArch64 | On-CPU、Off-CPU |
| PHP | 7.4~8.3 | x86_64、AArch64 | On-CPU、Off-CPU |
| Lua | Lua 5.1~5.4、LuaJIT 2.1 | x86_64、AArch64 | On-CPU |
| Python | CPython 3.10~3.13 | x86_64、AArch64 | On-CPU、Off-CPU、mem-alloc、mem-inuse、hbm-alloc、hbm-inuse |

Python 的 HBM Profile 来自目标进程调用的 CUDA API,而不是 CPython 内存分配器。PyTorch、vLLM 等 Python 应用通过受支持的 CUDA API 分配和释放显存时,可生成 `hbm-alloc` 和 `hbm-inuse`,具体采集范围和启动时序限制请参考[配置方法](./configuration/#cuda-hbm-profiling)。

脚本函数栈展开依赖 Agent 加载增强型 Continuous Profiler:

- 标准 Linux 内核版本须为 5.2 或更高。
- Kylin V10 SP3 v2207 的 `4.19.90-*.v2207.ky10.*` 内核也支持该能力,包括 x86_64 和 AArch64 架构。
- 普通 Linux 4.19 内核和 Kylin V10 SP3 v2101 内核不支持脚本函数栈展开。Agent 仍可使用通用 Profiler 采集满足条件的 Native 栈。
- 如果增强型 Profiler 加载失败,Agent 会自动降级为通用 Profiler;降级后不再提供 DWARF 和解释器脚本函数栈展开。

Agent 必须能够识别目标解释器版本,并读取目标进程的可执行文件及已加载的解释器共享库。不支持的运行时版本、识别失败或文件不可访问时,Profile 中仍可能包含 Native/运行时函数,但不会显示脚本函数。Python 内存剖析通过 CPython 的 `PyObject_Malloc/Free/Realloc` 和 `PyMem_RawMalloc/Free/Realloc` 公共符号采集对象分配与释放事件。

通过通用 eBPF On-CPU/Off-CPU Profiling 获取调用栈时,需满足以下两个前提条件:

Expand Down
63 changes: 60 additions & 3 deletions docs/zh/05-features/04-continuous-profiling/02-configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,31 @@ inputs:
only_in_container: false
rewrite_name: $3
enabled_features: [ebpf.profile.on_cpu, proc.gprocess_info]
- match_regex: \bjava( +\S+)* +-(?:cp|classpath) +\S+ +(?P<CLASS_NAME>[$_A-Za-z][$_0-9A-Za-z]*(?:\.[$_A-Za-z][$_0-9A-Za-z]*)*)
match_type: cmdline_with_args
only_in_container: false
rewrite_name: ${CLASS_NAME}
enabled_features: [ebpf.profile.on_cpu, proc.gprocess_info]
- match_regex: \bpython(\S)*( +-\S+)* +(\S*/)*([^ /]+)
match_type: cmdline_with_args
only_in_container: false
rewrite_name: $4
enabled_features: [ebpf.profile.on_cpu, proc.gprocess_info]
- match_regex: \b(?:lua|luajit)(\S)*( +-\S+)* +(\S*/)*([^ /]+)
match_type: cmdline_with_args
only_in_container: false
rewrite_name: $5
enabled_features: [ebpf.profile.on_cpu, proc.gprocess_info]
- match_regex: \bphp(\d+)?(-fpm|-cli|-cgi)?( +-\S+)* +(\S*/)*([^ /]+\.php)
match_type: cmdline_with_args
only_in_container: false
rewrite_name: $5
enabled_features: [ebpf.profile.on_cpu, proc.gprocess_info]
- match_regex: \b(node|nodejs)( +--\S+)* +(\S*/)*([^ /]+\.js)
match_type: cmdline_with_args
only_in_container: false
rewrite_name: $4
enabled_features: [ebpf.profile.on_cpu, proc.gprocess_info]
- match_regex: ^deepflow-
only_in_container: false
enabled_features: [ebpf.profile.on_cpu, proc.gprocess_info]
Expand All @@ -33,9 +53,9 @@ inputs:
上述配置的含义如下:

- **match_regex**: 进程匹配的正则表达式,匹配规则如下:
- 第一条规则匹配 Java 进程,例如 `java -jar app.jar`,并将进程名重写为 jar 包名
- 第二条规则匹配 Python 进程,例如 `python app.py`,并将进程名重写为 Python 脚本名
- 第三条规则匹配以 `deepflow-` 开头的进程
- 前两条规则分别匹配以 JAR 包和主类启动的 Java 进程,并将进程名重写为 JAR 包名或主类名
- 后续规则匹配 Python、Lua/LuaJIT、PHP 和 Node.js 进程,并将进程名重写为脚本名
- `^deepflow-` 规则匹配以 `deepflow-` 开头的进程
- 最后一条规则匹配所有进程
- **match_type**: 匹配类型,可选值:
- `cmdline_with_args`: 匹配完整命令行(包含参数)
Expand All @@ -49,6 +69,8 @@ inputs:
- `ebpf.profile.off_cpu`: 开启 Off-CPU 剖析,需要配置 `inputs.ebpf.profile.off_cpu.disabled: false`
- `ebpf.profile.memory`: 开启内存剖析,需要配置 `inputs.ebpf.profile.memory.disabled: false`

默认 Process Matcher 已为 Java、Python、Lua/LuaJIT、PHP、Node.js 和 DeepFlow 进程开启 `ebpf.profile.on_cpu`。如需采集 Off-CPU 或 Memory Profile,必须同时在目标进程的 `enabled_features` 中增加相应功能,并开启对应的全局 Profile 类型。Memory Profile 的解释器函数栈当前仅支持 Python。

同时可以使用 `inputs.proc.process_blacklist` 来忽略某些进程,其优先级比 `process_matcher` 高。

```yaml
Expand Down Expand Up @@ -77,6 +99,28 @@ inputs:
- **refresh_defer_duration**: Java 符号表的刷新延迟,避免高频刷新。
- **max_symbol_file_size**: Java 符号表占用的最大空间大小,单位为 GB,避免占用过大的 `/tmp` 空间。

# 解释器 Profiling

Node.js/V8、PHP、Lua 和 Python 的脚本函数栈展开默认启用。若主机上不运行某种解释器,可通过以下配置禁用对应的展开能力,以减少内核内存占用:

```yaml
inputs:
ebpf:
profile:
languages:
python_disabled: false
php_disabled: false
nodejs_disabled: false
lua_disabled: false
```

- 四项配置均默认为 `false`,表示启用对应解释器的函数栈展开。
- 配置项设为 `true` 后,目标进程的通用 Native Profile 仍可继续采集,但不再展开对应语言的脚本函数。
- 修改这些配置后需重启 Agent 生效。
- 全部启用时预计占用约 17~20 MB 内核内存。可关闭未使用的语言以降低内存占用。

语言开关只控制脚本函数栈展开。目标进程仍须由 `inputs.proc.process_matcher` 选中,并开启所需的全局 Profile 类型。支持版本、架构和内核条件请参考[能力和限制](./auto-profiling/#解释器运行时)。

# eBPF On-CPU Profiling

eBPF On-CPU Profiling 是默认开启的,但需要修改 `inputs.proc.process_matcher` 来指定进程列表。Agent 支持的配置参数如下:
Expand Down Expand Up @@ -145,6 +189,19 @@ inputs:
- **queue_size**:内存剖析组件内部的队列大小。
- 配置该选项可以参考采集器性能统计 `deepflow_agent_ebpf_memory_profiler` 中 `overwritten` 和 `pending` 指标,增大该配置使得前者为 0,后者不高于该配置即可。

## CUDA/HBM Profiling

HBM Profiling 不限制目标进程的编程语言。对于 Python/PyTorch/vLLM,必须确保真正执行 GPU 分配的 Worker 子进程也被 `inputs.proc.process_matcher` 匹配,并启用 `ebpf.profile.memory`;仅匹配父进程无法采集子进程的显存事件。`inputs.ebpf.profile.languages.python_disabled` 只控制 Python 脚本函数栈展开,不控制 HBM 事件采集。

当前 Agent 通过 uprobe 采集 `cudaMalloc`、`cudaFree`、`cuMemAlloc_v2` 和 `cuMemFree_v2` 调用,并据此生成:

- `hbm-alloc`:uprobe 生效后观测到的显存分配量及调用栈。
- `hbm-inuse`:根据已观测到的分配地址及后续释放事件计算的当前显存用量及调用栈。

Agent 约每 10 秒扫描一次进程。对于新匹配的非 Agent 进程,当前还会等待约 120 秒再解析已加载的 CUDA 库并挂载 Memory uprobe。uprobe 生效前发生的显存分配不会补采,也不会计入后续的 `hbm-inuse`。挂载完成后,如果进程持续调用上述受支持的 CUDA 分配和释放 API,则可正常生成新的 HBM Profile。

PyTorch/vLLM 等框架可能通过 Caching Allocator 预留大块显存,再在池内完成对象分配和释放;未再次调用上述 CUDA API 的池内操作不会产生 HBM 事件。当前也不采集 `cudaMallocAsync`、`cudaFreeAsync`、`cuMemAllocAsync` 等其他 CUDA 分配接口。

# Java CPU Profiling

Java CPU Profiling 通过 Java Agent 的 AsyncGetCallTrace(AGCT)持续采集 JVM 方法调用栈,并补全 Java JIT 方法符号。该功能独立于 eBPF On-CPU Profiling,必须同时满足以下两个条件才会采集目标进程:
Expand Down
23 changes: 19 additions & 4 deletions docs/zh/05-features/04-continuous-profiling/03-data.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,16 @@ curl -X POST http://${deepflow_server_node_ip}:$port/v1/profile/ProfileTracing \
API 请求参数说明:

- **app_service**:进程名
- **profile_language_type**:获取 eBPF Profile 数据时使用 `eBPF`
- **profile_event_type**:对于 eBPF On-CPU Profile 数据赋值为 `on-cpu` 即可
- **profile_language_type**:获取 Agent 采集的 eBPF Profile 数据时使用 `eBPF`。Node.js/V8、PHP、Lua 和 Python 的解释器函数栈也统一使用 `eBPF`,不会按运行时拆分为不同的 Language Type
- **profile_event_type**:对于本文涉及的解释器 Profile,根据支持类型使用 `on-cpu`、`off-cpu`、`mem-alloc`、`mem-inuse`、`hbm-alloc` 或 `hbm-inuse`
- **tag_filter**:当进程名冲突时,可使用其他 Tag 过滤
- 例如 `"tag_filter": "pod_cluster='prod-cluster' AND pod_ns='app'"`
- **time_start**、**time_end**:时间范围

`profile.in_process` 表支持使用的 `tag_filter` 字段如下:
[csv-profile-tag-filters](https://raw.githubusercontent.com/deepflowio/deepflow/main/server/querier/db_descriptions/clickhouse/tag/profile/in_process.ch)

API 返回结果示例:
API 返回结果示例(以下以 CPU Profile 为例)

```json
{
Expand Down Expand Up @@ -99,6 +99,8 @@ API 返回结果说明:
- `[k] function_name`:Linux 内核函数、CUDA 动态链接库函数([libcuda](https://developer.nvidia.com/cuda-toolkit)、[libcublas](https://developer.nvidia.com/cublas) 等)
- `[l] function_name`:动态链接库中的函数
- `function_name`:表示应用程序的业务函数
- `function_name [JS]`:Node.js/V8 的 JavaScript 函数,例如 `workLoop [JS]`
- `Class::method:line [PHP]` 或 `function:line [PHP]`:PHP 方法或函数及其源码行号
- `$app_service`:火焰图最顶层的节点,名字为进程名
- 除此之外,当函数名未成功翻译时,可能显示为如下几种形式之一
- `[/tmp/perf-29887.map]`:方括号中为进程号 29887 的 Java 进程符号文件名,函数地址未能在该文件中找到。Java 进程符号文件会自动周期性生成,此时一般由于该符号文件生成时该函数尚未加载导致。
Expand All @@ -117,6 +119,19 @@ API 返回结果说明:

使用 API 的返回结果,可以绘制**指定进程**的 CPU 火焰图。

## 确认解释器函数栈

Node.js/V8 和 PHP 脚本帧分别带有 `[JS]`、`[PHP]` 后缀。Python 和 Lua 的脚本函数也会与 Native/运行时函数一起出现在火焰图中,但展示格式可能随运行时版本和符号内容变化。即使查询解释器进程,`profile_language_type` 仍须使用 `eBPF`。

如果 Profile 中只有 Native 或解释器运行时函数,没有业务脚本函数,请依次检查:

1. 运行时版本和主机架构是否位于[支持范围](./auto-profiling/#解释器运行时)内。
2. 内核是否支持增强型 Continuous Profiler,以及 Agent 是否出现 `falling back to common (no DWARF/unwind)` 降级日志。
3. 目标进程是否已由 Process Matcher 开启所需 Profile 类型,且对应的 `inputs.ebpf.profile.languages` 开关未禁用。
4. Agent 是否能读取目标进程的可执行文件及已加载的解释器共享库,日志中是否存在版本识别或符号读取失败。

配置方法请参考[配置方法](./configuration/)。

# 获取指定主机的 Profile

## Grafana Panel
Expand Down Expand Up @@ -185,7 +200,7 @@ API 返回结果说明:

| Function Type | 含义 | Profile Event Type | 特征 |
| ------------- | -------------- | ------------------ | ---------------------------------------- |
| O | 对象类型 | `mem-*` | Memory Profile 的叶子节点 |
| O | 对象类型 | `mem-*`、`hbm-*` | Memory/HBM Profile 的叶子节点 |
| H | 云主机 | `*` | 等于 `Total` 的根节点 |
| P | 进程 | `*` | `[p] ` 开头,以及不等于 `Total` 的根节点 |
| T | 线程 | `*` | `[t] ` 开头 |
Expand Down
Loading
Loading