lmcache tool#
lmcache tool 命令将与 LMCache 捆绑在一起的离线分析工具进行分组。
lmcache tool <tool-name> <action> [options]
提供了三个工具:cache-simulator 重放查找日志,transfer-channel-benchmark 测量点对点读取吞吐量,以及 flamegraph 记录任何正在运行的进程。
备注
cache-simulator 依赖于可选的 plot 附加组件(sortedcontainers / matplotlib)。如果它们未安装,子命令将会在 CLI 中静默省略。安装附加组件以启用它。
cache-simulator#
通过 LRU 缓存重放 LMCache 查找哈希 JSONL 日志,以测量 KV Cache 的令牌命中率。它有三个操作:
lmcache tool cache-simulator {simulate,sweep,gen-dataset} [options]
操作 |
描述 |
|---|---|
|
在固定的缓存容量下重放日志;打印文本报告并保存 7 面板的统计 PNG。 |
|
在一系列缓存容量中进行扫描,并保存命中率与容量的 PNG 图像。 |
|
从查找哈希 JSONL 日志生成一个 |
每个操作都有其自己的标志。运行内置帮助以获取完整列表:
lmcache tool cache-simulator simulate --help
lmcache tool cache-simulator sweep --help
lmcache tool cache-simulator gen-dataset --help
transfer-channel-benchmark#
测量 LMCache 传输通道(lmcache/v1/distributed/transfer_channel/)的读取吞吐量(GB/s),用于批量点对点读取。它通过与生产使用的相同 L1MemoryManager 分配传输的对象,因此它测试真实的内存路径,而不是原始张量。
基准测试以 两个进程 运行,一个 server 注册源缓冲区并提供其对象目录,另一个 client 读取这些对象的子集并报告吞吐量:
# Terminal 1: the source
lmcache tool transfer-channel-benchmark --role server \
--url 127.0.0.1:7600 --buffer-size 8GB --object-size 10MB
# Terminal 2: the reader
lmcache tool transfer-channel-benchmark --role client \
--url 127.0.0.1:7600 --object-size 10MB --num-objects 100 --iters 5
标志 |
描述 |
|---|---|
|
必填。 |
|
将传输通道实现用于基准测试(默认: |
|
服务器:绑定地址。客户端:要读取的服务器广告 URL(默认: |
|
服务器:总共注册的 L1 源缓冲区,例如 |
|
每个传输对象的大小和对齐方式;两侧必须匹配。 |
|
每次迭代读取的对象数量,以及测量的迭代次数。 |
|
在传输后检查读取的字节与源的匹配情况。 |
--url、--object-size 和 --page-size 的值必须在两个进程之间匹配。运行任一侧并使用 --help 获取完整列表,包括客户端自己的 --listen-url 和目录的 --control-url。
火焰图#
将分析器附加到已运行的进程,记录固定时间,并渲染火焰图以查找瓶颈。
它提供了一个统一的接口,支持广泛采用的分析工具(py-spy、perf 和 bcc),每个工具都生成一个火焰图。单个 --mode 涵盖了整个范围,从 Python 和 GIL 争用到 CPU 时间、内核帧和阻塞时间:您可以根据想要查看的内容选择模式,而不是根据要运行的工具,从而在所有六个工具中获得一致的输出、默认值和权限检查。它包装这些工具而不是替换它们(它指定要安装的内容,而不实际安装),因此用户或开发者可以找到痛点或资源密集型代码路径,而无需手动将工具拼接在一起。
标志 |
默认 |
描述 |
|---|---|---|
|
(必需) |
处理以进行性能分析。 |
|
|
|
|
|
记录的秒数。 |
|
(自动) |
SVG 路径。默认 |
|
(自动) |
FlameGraph 脚本目录; |
用法#
# Which threads of an MP cache server hold the GIL, sampled for 20s
lmcache tool flamegraph --pid $(pgrep -f 'lmcache server') --mode gil --duration 20
# Capture GIL, CPU, and blocked-time views in one sweep (one SVG per mode)
lmcache tool flamegraph --pid $(pgrep -f 'lmcache server') --mode gil,on-cpu,off-cpu
使用此命令可以对 **真实的、未修改的进程**(在实际流量下的生产或 vLLM 驱动的服务器、空闲服务器或任何任意 PID)进行性能分析,而无需搭建基准测试工具。bench 命令(lmcache bench l2 / lmcache bench server)则是在它们生成的合成负载下对进程进行性能分析。
模式#
LMCache 主要是用 Python 编写的,因此第一个问题通常是 Python 时间的去向以及 GIL 的争用情况。要分析 Python 执行或 GIL 争用情况,请使用 gil / wall (py-spy):每个线程一个根帧,附加到 未修改的 CPython 目标,但没有内核帧。
gil:仅显示持有 GIL 的线程,因此解释器锁的争用直接可见(这是实时服务器的默认设置)。
墙:每个线程的墙钟时间,包括被阻塞的线程。
但是 LMCache 还使用 C++、Rust 和 CUDA 来加速热路径并释放 GIL,而 py-spy 并未看到这些。**要分析 CPU/IO 时间、内核帧、上下文切换或非 Python 进程**(或获取整个进程花费时间和阻塞的跨语言视图),请使用整个进程模式(perf / bcc):每个线程、内核帧、调度器活动、任何进程,但合并为一个图表。
在 CPU 上 (
perf): CPU 周期 的去向。离线 CPU (
offcputime-bpfcc): 花费在 阻塞 上的时间(I/O,锁)。唤醒 (
wakeuptime-bpfcc): 唤醒 的堆栈,结束其他线程的睡眠。offwake (
offwaketime-bpfcc):off-cpu和wakeup的结合,每个被阻塞的栈与唤醒它的线程的栈相连(唤醒者的部分反向绘制在顶部)。当off-cpu显示出一个大的阻塞塔时使用它,以便找出原因。
它们是如何工作的。 所有运行作为外部进程;不同之处在于 数据的收集位置,是在内核中(perf, bcc)还是通过读取目标的内存(py-spy):
perf 以 99 Hz 的频率对 CPU 进行采样,记录正在运行的线程的调用栈,因此它只看到 CPU 上的工作,并通过帧指针遍历本地调用栈。
bcc 不是 被采样的:eBPF 程序在调度事件上触发,因此它可以测量 perf 无法测量的 阻塞 时间,代价随着目标的上下文切换率而增加。加载 eBPF 需要特权。
py-spy 在用户空间工作,通过
process_vm_readv读取目标的内存,并使用--nonblocking``(无暂停);它只看到 Python 框架,并需要 ``ptrace权限。
``--pid P`` 的等效原始命令:
gil py-spy record --gil --rate 200 --threads --idle --nonblocking --pid P
wall py-spy record --rate 200 --threads --idle --nonblocking --pid P
on-cpu perf record -F 99 -g -p P -> perf script | stackcollapse-perf.pl | flamegraph.pl
off-cpu sudo offcputime-bpfcc -df -p P | flamegraph.pl --colors io
wakeup sudo wakeuptime-bpfcc -f -p P | flamegraph.pl --colors wakeup
offwake sudo offwaketime-bpfcc -df -p P | flamegraph.pl --colors chain
本地堆栈需要帧指针。 perf/bcc 模式通过帧指针展开本地堆栈(perf 通过 -g,bcc 通过 bpf_get_stackid),因此使用 -fomit-frame-pointer 构建的目标在两者中都会显示损坏的 C 堆栈;请使用 -fno-omit-frame-pointer 重新构建。py-spy 不受影响(它读取解释器),但仅看到 Python。
安装#
每种模式都封装了一个必须在运行命令的主机上安装的外部工具(与目标相同的主机);缺少工具时会快速失败并指明需要安装的内容。
py-spy (
wall/gil): 读取解释器并渲染自己的 SVG。使用pip install py-spy安装。Linux
perf(on-cpu):sudo apt install linux-tools-generic(Debian / Ubuntu) 或sudo dnf install perf(Fedora / RHEL);该软件包必须与正在运行的内核匹配。使用下面的 FlameGraph 脚本进行渲染。bcc (
off-cpu/wakeup/offwake):sudo apt install bpfcc-tools(Debian / Ubuntu) 或sudo dnf install bcc-tools(Fedora / RHEL)。其*-bpfcc工具在运行时也需要sudo。FlameGraph,由 Brendan Gregg 提供:折叠并渲染 perf/bcc SVG。首次使用时克隆到
~/FlameGraph``(需要 ``git);或者将--flamegraph-scripts-dir指向现有的检出版本。
权限#
在 perf/bcc 模式中命名 Python 框架 需要目标在启动时设置 ``PYTHONPERFSUPPORT=1``(其 perf 跳板图);您无法在运行中的进程上启用它。
警告
如果未设置: perf/bcc 仍然会记录,但 Python 框架会合并为
[unknown]``(仅 C/本地堆栈)。使用 ``gil/wall,或在设置变量的情况下重新启动目标。如果设置了: 这会在进程的生命周期内增加每次调用的固定开销,因此请将其保留用于专门的性能分析会话,而不是生产环境。
系统设置调整(裸机 / 虚拟机)。 每个工具需要内核权限;设置适合您模式的权限,或者以 root 身份运行,这样可以满足所有三种情况:
wall/gil(py-spy) 通过ptrace读取目标的内存,受 Yama 限制。Ubuntu / Debian 默认将ptrace_scope设置为 ``1``(仅跟踪子进程),这会阻止附加到服务器:sudo sysctl -w kernel.yama.ptrace_scope=0``CAP_SYS_PTRACE``(或 root)可以绕过它;当被阻止时,py-spy 也会打印此提示。
on-cpu(perf) 通过perf_event_open进行采样。级别3``(Debian 的附加功能)会直接阻止它,任何高于 ``2的级别会使perf record静默写入一个空文件,因此请降低它:sudo sysctl -w kernel.perf_event_paranoid=2off-cpu/wakeup/offwake(bcc) 加载一个 eBPF 程序,因此它们的*-bpfcc工具需要 ``sudo``(root 权限)。
备注
在容器中,使用 py-spy 模式。 perf 和 bcc 依赖于主机范围的内核状态,容器不应更改,因此在主机上运行它们(上述设置适用于此)。
py-spy 可以在容器内工作。请在与目标 相同的容器 中运行分析器(或使用 --pid=container:<target> 共享其 PID 命名空间),并使用 --cap-add SYS_PTRACE 启动容器,这是上述 ptrace_scope 设置的容器等效项:
docker run --cap-add SYS_PTRACE ... <image>
pip install py-spy
lmcache tool flamegraph --pid <target-pid> --mode gil
如果平台不授予 ``CAP_SYS_PTRACE``(如 RunPod、某些 Kubernetes),您仍然可以对自己启动的进程进行分析:跟踪您自己的子进程不需要任何权限,因此请在 py-spy 下启动目标,而不是附加到它上。
py-spy record --rate 200 --format flamegraph --threads --idle --gil \
--subprocesses --duration 30 -o /workspace/flame.svg \
-- <the target launch command>
成本#
这些机制为每种模式提供了不同的成本 形状:
perf: 有界,固定的 99 Hz 采样,因此开销是恒定的;成本是磁盘,因为
perf.data随着持续时间 × 速率 × 线程 × 深度而增长(渲染后删除)。bcc: 无界,在每个调度程序事件上触发,成本与目标的事件速率相关,因此繁忙的服务会不断触发探针。输出非常小。
py-spy: 最轻量级的 在目标上,其采样运行在目标的 CPU 上,而 perf 和 bcc 则占用目标的周期。
在生产服务器上,优先使用 wall / gil 并保持 --duration 较短;如果需要整个进程模式,on-cpu 的有限成本比在繁忙目标上的 bcc 模式更安全。