关于 ln-811-performance-profiler
ln-811-performance-profiler 是面向开发者的性能分析技能,用于调查文件、端点或流水线的运行缓慢问题。它采集实际运行指标和函数级数据,生成结构化性能图谱与瓶颈报告。
主要功能
- 01采集多项运行指标
- 02函数级分析与插桩
- 03发现测试或生成基准测试
- 04瓶颈分类与性能图谱
适用场景
- 01定位 CPU、内存、I/O 或耗时瓶颈
- 02分析端点或处理流水线
- 03在优化前建立性能基线
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ levnikolaevich/ claude-code-skills --skill ln-811-performance-profiler安装后在 Claude Code 中输入/ln-811-performance-profiler确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/benchmark_generation.mdbottleneck_classification.mdci_tool_detection.mdcoordinator_summary_contract.mdlatency_estimation.mdmonitor_integration_pattern.mdoutput_normalization.md详细介绍
路径: 文件路径(
references/、../ln-*)相对于此技能目录。
ln-811-performance-profiler
类型: L3 Worker 类别: 8XX 优化
运行时分析器:执行优化目标,测量多项指标(CPU、内存、I/O、时间),为代码添加检测以获取逐函数细分数据,并根据真实数据生成标准化性能图谱。
概览
| 方面 | 详情 |
|---|---|
| 输入 | 问题描述:目标(文件/端点/流水线)+ 观察到的指标 |
| 输出 | 性能图谱(多指标、逐函数)、疑点堆栈、瓶颈分类 |
| 模式 | 发现测试 → 基线运行 → 静态分析 → 深度分析 → 性能图谱 → 报告 |
工作流
阶段: 发现测试 → 基线运行 → 静态分析 → 深度分析 → 性能图谱 → 报告
阶段 0:发现/创建测试
必须阅读: 加载 references/ci_tool_detection.md 以检测测试框架。
必须阅读: 加载 references/benchmark_generation.md,以便在没有基准测试时自动生成。
查找或创建用于执行优化目标的命令。输出两项:test_command(性能分析/测量)和 e2e_test_command(功能安全门禁)。
步骤 1:发现 test_command
| 优先级 | 方法 | 操作 |
|---|---|---|
| 1 | 用户提供 | 用户指定测试命令或 API 端点 |
| 2 | 发现现有 E2E 测试 | 搜索测试文件中的目标入口点(首次匹配后停止) |
| 3 | 创建测试脚本 | 按 references/benchmark_generation.md 生成脚本到 .hex-skills/optimization/{slug}/profile_test.sh |
E2E 发现协议(首次匹配后停止):
| 优先级 | 方法 | 方式 |
|---|---|---|
| 1 | 基于路由搜索 | 在 e2e/集成测试文件中搜索入口点路由 |
| 2 | 基于函数搜索 | 搜索入口点函数名称 |
| 3 | 基于模块搜索 | 搜索入口点模块的导入语句 |
创建测试(未找到现有测试时):
| 目标类型 | 生成的脚本 |
|---|---|
| API 端点 | curl -w "%{time_total}" -o /dev/null -s {endpoint} |
| 函数 | 按 references/benchmark_generation.md 生成特定技术栈的基准测试 |
| 流水线 | 使用测试输入调用完整流水线 |
步骤 2:发现 e2e_test_command
如果 test_command 来自 E2E 发现(步骤 1 优先级 2):e2e_test_command = test_command。
否则,再次运行 E2E 发现协议(相同的 3 级优先级表),以查找单独的功能安全测试。
如果未找到:e2e_test_command = null,记录:WARNING: No e2e test covers {entry_point}. Full test suite serves as functional gate.
输出
| 字段 | 描述 |
|---|---|
test_command | 用于性能分析/测量的命令 |
e2e_test_command | 用作功能安全门禁的命令(可以与 test_command 相同,也可以为 null) |
e2e_test_source | 发现方式:user / route / function / module / none |
阶段 1:基线运行(多指标)
使用系统级性能分析运行 test_command。同时捕获:
| 指标 | 捕获方式 | 条件 |
|---|---|---|
| 墙钟时间 | time 封装器或测试框架 | 始终 |
| CPU 时间(user+sys) | /usr/bin/time -v 或语言分析器 | 始终 |
| 内存峰值(RSS) | /usr/bin/time -v(Max RSS)或 tracemalloc / process.memoryUsage() | 始终 |
| I/O 字节数 | /usr/bin/time -v 或结构化日志 | 怀疑存在 I/O 时 |
| HTTP 往返次数 | 从结构化日志或应用指标中计数 | 调用图中存在网络 I/O 时 |
| GPU 利用率 | nvidia-smi --query-gpu | 仅当技术栈中检测到 CUDA/GPU 时 |
基线协议
| 参数 | 值 |
|---|---|
| 运行次数 | 3 |
| 指标 | 中位数 |
| 预热 | 丢弃 1 次运行 |
| 输出 | baseline — 多指标快照 |
监控分析器运行(Claude Code 2.1.98+)
**必须阅读:**加载 references/monitor_integration_pattern.md
在基线和深度分析器运行期间:
Monitor(command="{test_command} 2>&1", timeout_ms=300000, description="profiler run N")
立即检测崩溃或无限循环。备用方案:使用 Bash 和 timeout。
阶段 2:静态分析 → 插桩点
**必须阅读:**加载 bottleneck_classification.md
根据代码和构建疑点调用栈追踪调用链。**目的:**指导第 3 阶段的插桩位置。
步骤 1:追踪调用链
从入口点开始,按深度优先方式追踪(最大深度为 5)。每一步都要阅读完整的函数体。
**跨服务追踪:**如果协调器提供了 service_topology,且某一步会通过 HTTP/gRPC 调用另一个可访问其代码的服务:
| 情况 | 操作 |
|---|---|
| HTTP 调用的服务,其代码位于子模块/单体仓库中 | 跟进该服务的处理程序:解析路由 → 追踪处理程序代码(新服务的深度重置为 0) |
| HTTP 调用的服务,其代码不可访问 | 归类为 External,记录延迟估算值 |
| 调用已知服务的 gRPC/消息队列 | 与 HTTP 相同——如果代码可访问,则跟进处理程序 |
在每一步记录 service: "{service_name}",以追踪其所属服务。performance_map 的 steps 树可以跨越多个服务。
**深度优先规则:**如果可以访问被调用服务的代码,就必须在该服务内部进行分析。绝不能在未分析其内部实现的情况下,将可访问的服务归类为“External/慢”。“慢”是症状,不是诊断。
**针对每个瓶颈追问 5 个为什么:**报告瓶颈之前,连续追问“为什么?”,直到找到配置/架构层面的原因:
- “什么很慢?”→ 对齐服务(5.9 秒)2. “为什么?”→ 6 对 × 每对约 1 秒 3. “为什么每对约 1 秒?”→ O(n²) mwmf 计算 4. “为什么是 O(n²)?”→ 库默认值,而非生产配置 5. “为什么使用默认值?”→ 未配置
matching_methods→ 根因 = 配置
步骤 2:分类并扫描疑点
对于每一步,按类型(CPU、I/O-DB、I/O-Network、I/O-File、Architecture、External、Cache)进行分类,并扫描性能问题。
疑点检查清单(最低要求,并非限制):
| 类别 | 检查内容 |
|---|---|
| 连接管理 | 是否每个请求都创建客户端?是否缺少连接池?是否缺少复用? |
| 数据流 | 是否多次读取数据?是否过度获取数据?是否进行了不必要的转换? |
| 异步模式 | 是否在异步上下文中执行同步 I/O?是否存在没有数据依赖的顺序 await? |
| 资源生命周期 | 是否有未关闭的连接?临时文件?循环中是否累积内存? |
| 配置 | 是否硬编码超时时间?是否使用默认连接池大小?是否缺少批次大小配置? |
| 冗余工作 | 是否在多个层级执行相同的验证?是否重复加载相同数据? |
| 架构 | 是否在循环中存在 N+1 问题?是否未使用批处理 API?是否未使用缓存基础设施?是否本可并行却按顺序执行? |
| (开放项) | 发现的其他任何问题——检查清单不会限制发现范围 |
步骤 2b:疑点去重
**必须阅读:**加载 references/output_normalization.md
生成所有调用链步骤的疑点后,按照 §1-§2 进行规范化和去重:
- 规范化疑点描述(将具体值替换为占位符)
- 合并不同步骤中的相同疑点 → 合并为单个条目,并设置
affected_steps: [list] - 示例:在步骤 1.1、1.2、1.3 中发现“缺少连接池” → 合并为一个疑点,其
affected_steps: ["1.1", "1.2", "1.3"]
步骤 3:验证并映射到插桩点
FOR each suspicion:
1. VERIFY: follow code to confirm or dismiss
2. VERDICT: CONFIRMED → map to instrumentation point | DISMISSED → log reason
3. For each CONFIRMED suspicion, identify:
- function to wrap with timing
- I/O call to count
- memory allocation to track
性能分析器选择(按技术栈)
| 技术栈 | 非侵入式性能分析器 | 侵入式(非侵入式分析不足时) |
|---|---|---|
| Python | py-spy、cProfile | time.perf_counter() 装饰器 |
| Node.js | clinic、--prof | console.time() 包装器 |
| Go | pprof(内置) | 通常不需要 |
| .NET | dotnet-trace | Stopwatch 包装器 |
| Rust | cargo flamegraph | std::time::Instant |
**技术栈检测:**参见 references/ci_tool_detection.md。
第 3 阶段:深入性能分析
性能分析器层级(按需升级)
| 级别 | 工具示例 | 显示内容 | 使用时机 |
|---|---|---|---|
| 1 | py-spy、cProfile、pprof、dotnet-trace | 函数级热点 | 始终使用——初步分析 |
| 2 | line_profiler、逐行计时 | 热点函数内的逐行耗时 | 已找到热点函数,但原因不明 |
| 3 | tracemalloc、memory_profiler | 逐行内存分配 | 基线内存指标异常 |
步骤 1:非侵入式性能分析(优先)
使用 1 级性能分析器运行 test_command,无需修改代码即可获取各函数的耗时明细。
步骤 2:升级决策
运行 1 级性能分析器后,根据第 2 阶段的怀疑项评估结果:
| 性能分析结果 | 操作 |
|---|---|
| 已找到热点函数,耗时明细证实了怀疑 | 完成——继续第 4 阶段 |
| 已找到热点函数,但内部原因不明(单个函数内的 CPU 与 I/O) | 升级到 2 级(逐行计时) |
| 基线内存异常(峰值或差值) | 升级到 3 级(内存分析器) |
| 多项怀疑尚未排除——性能分析器粒度不足 | 转到步骤 3(定向插桩) |
| 性能分析器不可用,或开销超过墙钟时间的 20% | 转到步骤 3(定向插桩) |
停止条件(性能分析器升级)
| 条件 | 操作 |
|---|---|
| 已找到热点且原因明确 | 停止——继续生成性能映射 |
| 已用尽全部 3 个性能分析器级别 | 停止——根据现有最佳数据生成映射 |
| 插桩导致测试失败 | 停止——撤销插桩,仅使用非侵入式数据 |
| 性能分析器开销超过墙钟时间的 20% | 停止——跳过并转到定向插桩 |
步骤 3:定向插桩(主动进行)
沿调用栈,在第 2 阶段步骤 3 中确定的插桩点添加计时和日志记录:
1. FOR each CONFIRMED suspicion without measured data:
Add timing wrapper around target function/I/O call
Add counter for I/O round-trips if network/DB suspected
(cross-service: instrument in the correct service's codebase)
2. Re-run test_command (3 runs, median)
3. Collect per-function measurements from logs
4. Record list of instrumented files (may span multiple services)
| 插桩类型 | 时机 | 示例 |
|---|---|---|
| 计时包装器 | 始终用于尚未排除的怀疑项 | 在函数调用周围使用 time.perf_counter() |
| I/O 调用计数器 | 怀疑存在网络或数据库瓶颈时 | 统计循环中的 HTTP 请求和数据库查询次数 |
| 内存快照 | 怀疑内存持续累积时 | 在操作前后调用 tracemalloc.get_traced_memory() |
**保留插桩。**执行器会在优化后复用这些插桩进行逐函数对比,然后在完成本轮后清理。请在输出中报告 instrumented_files。
第 4 阶段:生成性能映射
采用标准化格式——供下游使用,内容将写入 .hex-skills/optimization/{slug}/context.md。
performance_map:
test_command: "uv run pytest tests/automated/e2e/test_example.py -s"
baseline:
wall_time_ms: 7280
cpu_time_ms: 850
memory_peak_mb: 256
memory_delta_mb: 45
io_read_bytes: 1200000
io_write_bytes: 500000
http_round_trips: 13
steps: # service field present only in multi-service topology
- id: "1"
function: "process_job"
location: "app/services/job_processor.py:45"
service: "api" # optional — which service owns this step
wall_time_ms: 7200
time_share_pct: 99
type: "function_call"
children:
- id: "1.1"
function: "translate_binary"
wall_time_ms: 7100
type: "function_call"
children:
- id: "1.1.1"
function: "tikal_extract"
service: "tikal" # cross-service: code traced into submodule
wall_time_ms: 2800
type: "http_call"
http_round_trips: 1
- id: "1.1.2"
function: "mt_translate"
service: "mt-engine"
wall_time_ms: 3500
type: "http_call"
http_round_trips: 13
bottleneck_classification: "I/O-Network"
bottleneck_detail: "13 sequential HTTP calls to MT service (3500ms)"
top_bottlenecks:
- step: "1.1.2", type: "I/O-Network", share: 48%
- step: "1.1.1", type: "I/O-Network", share: 38%
第 5 阶段:报告
报告结构
profile_result:
entry_point_info:
type: <string> # "api_endpoint" | "function" | "pipeline"
location: <string> # file:line
route: <string|null> # API route (if endpoint)
function: <string> # Entry point function name
performance_map: <object> # Full map from Phase 4
bottleneck_classification: <string> # Primary bottleneck type
bottleneck_detail: <string> # Human-readable description
top_bottlenecks:
- step, type, share, description
optimization_hints: # CONFIRMED suspicions only (Phase 2)
- hint with evidence
suspicion_stack: # Full audit trail (confirmed + dismissed)
- category: <string>
location: <string>
description: <string>
verdict: <string> # "confirmed" | "dismissed"
evidence: <string>
verification_note: <string>
e2e_test:
command: <string|null> # E2E safety test command (from Phase 0)
source: <string> # user / route / function / module / none
instrumented_files: [<string>] # Files with active instrumentation (empty if non-invasive only)
wrong_tool_indicators: [] # Empty = proceed, non-empty = exit
工具选择错误的指标
| 指标 | 条件 |
|---|---|
external_service_no_alternative | 实测耗时的 90% 以上花在外部服务上,且没有批处理、缓存或并行处理路径 |
within_industry_norm | 实测耗时在该操作类型的预期范围内 |
infrastructure_bound | 瓶颈在硬件(通过系统指标测得) |
already_optimized | 代码已采用最佳模式(经怀疑项扫描确认) |
错误处理
| 错误 | 恢复方式 |
|---|---|
| 无法解析入口点 | 阻止:file/function not found at {path} |
| 未修改代码时测试命令失败 | 阻止:test fails before profiling — fix test first |
| 当前技术栈没有可用的分析器 | 回退到侵入式插桩(阶段 3 步骤 2) |
| 插桩导致测试失败 | 立即还原:git checkout -- . |
| 调用链过深(> 5 层) | 在深度 5 处停止,并注明已截断 |
| 无法判断步骤类型 | 默认设为“Unknown”,使用实测时间 |
| 未检测到 I/O(纯 CPU) | 分类为 CPU,重点分析算法性能 |
参考资料
- bottleneck_classification.md — 瓶颈分类体系
- latency_estimation.md — 延迟估算启发式方法(仅静态模式下的回退方案)
references/ci_tool_detection.md— 技术栈/工具检测references/benchmark_generation.md— 各技术栈的基准测试模板
运行时摘要产物
必须阅读: 加载 references/coordinator_summary_contract.md
生成 optimization-worker 摘要封装。
托管模式:
ln-810会传入确定性的runId和准确的summaryArtifactPath- 将摘要写入提供的
summaryArtifactPath
独立模式:
- 忽略
runId和summaryArtifactPath - 将摘要写入
.hex-skills/runtime-artifacts/runs/{run_id}/optimization-worker/ln-811--{identifier}.json
完成定义
- 已发现或为优化目标创建测试命令
- 已发现端到端安全测试(或已记录其不可用)
- 已测量基线:运行时间、CPU、内存(运行 3 次,取中位数)
- 已追踪调用图并阅读函数体
- 已构建疑点列表:每项疑点均已验证并映射到插桩点
- 已完成深度分析(优先采用非侵入式方法,必要时采用侵入式方法)
- 已报告已插桩文件(清理工作由执行器负责)
- 已按标准格式构建性能图谱(使用真实测量数据)
- 已根据测量数据识别出最主要的 3 个瓶颈
- 已根据真实指标评估错误工具指示器
- optimization_hints 仅包含有测量证据支持的已确认疑点
- 已根据测量结果撰写报告
- 已将优化分析产物写入共享位置
版本: 3.0.0 最后更新: 2026-03-15