AI 驱动的跨平台移动端性能分析 CLI 工具。通过自然语言交互,自动采集设备性能 trace,分析性能瓶颈,并将热点归因到源码。
当前已实现 Android 平台完整支持,HarmonyOS 和 iOS 平台支持规划中。
- 🧠 自然语言交互 — 用中文描述性能问题,AI 自动路由到对应分析流程
- 📊 全量分析流水线 — 自动采集 → 分析 → 源码归因 → 报告生成
- 🔍 SI$ 源码归因 — 通过 TraceHook tag 将性能热点精确归因到源码位置(含 IO 切片归因)
- 🛡️ 健壮性保障 — 全链路异常处理,Agent 崩溃不丢会话状态
- ⚡ Token 效率优化 — SQL 结果智能压缩(统计摘要+异常采样)、消息窗口裁剪、路由 token 限制、流式输出
- ✅ 分析质量验证 — L1 格式检查 + L2 一致性验证,自动检测 LLM 输出遗漏和不一致,支持重试补充
- 🔒 Release 零开销 — Release 变体为纯 no-op stubs,编译器内联后零运行时开销
- 💬 实时通信 — WebSocket CLI↔App 双向通信,支持心跳检测和断线重连
- 🖥️ Perfetto UI 交互 — 自托管 Perfetto UI + SI Bridge 插件,框选时间范围即可 AI 分析
- ⌨️ 交互增强 — Tab 补全、全局异常保护、启动前置条件检查
- 🚀 冷启动分析 — 自动识别启动阶段(进程启动→Application.onCreate→Activity.onCreate→首帧),定位启动瓶颈
- 🤖 Headless/CI 模式 — 非交互式运行全量分析流水线,支持 JSON 结构化输出,可直接集成 CI/CD
- 🌐 IO 追踪 — 默认启用网络/数据库/图片加载 IO Hook,独立收集 IO 切片并归因到源码
- 🔬 Perfetto Stdlib 模块 — 11 个 stdlib 模块深度分析:锁竞争、Binder 事务、启动指标(TTID/TTFD)、GC 事件、ANR 检测、Slice CPU 时间、输入延迟分解、调度延迟、OOM/RSS/Swap、CPU 利用率、SurfaceFlinger 帧匹配
- 🧩 维度注册体系 — 7 个可扩展分析维度(锁竞争/调度延迟/GC/文件IO/内存趋势/Binder/CPU降频),插件式架构,
@register_dimension装饰器自动注册 - 📚 Prompt Skill 系统 — 知识/指令分离架构,维度专家知识按需注入 LLM,每个 Agent 只加载所需领域知识
# 安装依赖
uv sync
# 配置 LLM(复制示例配置并填入 API Key)
cp .env.example .env
# 编辑 .env: SI_API_KEY=your-api-key
# 启动 CLI(自动检查 adb/API key,启动 WS server + adb reverse)
uv run smartinspector --src /path/to/your/app/source
# adb连接手机
# 交互式使用(支持 Tab 补全 slash 命令)
# 自然语言开启采集和分析
you> 分析冷启动耗时
# 指令开启采集分析
you> /full
# 冷启动分析(跳过等待,直接开始采集)
you> /full --no-wait
# 打开perfetto ui
you> /open非交互式运行全量分析流水线,适合 CI/CD 集成:
# 分析已有 trace 文件,输出 JSON 报告到 stdout
uv run smartinspector --ci --trace trace.pb --format json --src ./app/src
# 从设备采集 trace 并生成 Markdown 报告到文件
uv run smartinspector --ci --target com.example.app --duration 5000 --output report.md
# JSON 格式输出示例(适合自动化解析)
uv run smartinspector --ci --trace trace.pb --format json | jq '.issues[] | select(.severity == "P0")'SmartInspector 提供 Model Context Protocol (MCP) Server,将所有分析指令暴露为 MCP Tools,供外部 AI Agent(Claude Desktop、OpenClaw、Cursor 等)直接调用。
# 安装依赖(mcp 已包含在项目依赖中)
uv sync
# 启动 MCP Server(stdio transport)
uv run si-mcp首次使用时调用 si_init 完成会话配置,参数在整个会话中持久化:
si_init(
source_dir="/path/to/app/source", # 源码目录(源码归因需要)
target_process="com.example.app", # 默认目标包名
debug=False, # 启用 debug 日志
api_key="your-api-key", # LLM API Key(也可通过环境变量设置)
base_url="https://api.deepseek.com", # API Base URL
model="deepseek-chat" # LLM 模型名
)| 工具 | 说明 |
|---|---|
si_full |
全量流水线:采集 → 分析 → 源码归因 → 报告 |
si_trace |
采集 + 分析 trace(跳过归因) |
si_analyze |
分析已有 trace 文件 |
si_startup |
冷启动分析(自动 force-stop + 启动 App) |
si_quick |
快速确定性分析(不调用 LLM,秒级完成) |
si_ci_analyze |
CI/自动化非交互分析,支持 JSON 输出 |
si_compare |
对比两份分析报告 |
完整工具列表(23 个)和参数说明见 docs/mcp-server.md。
在 ~/Library/Application Support/Claude/claude_desktop_config.json 中添加:
{
"mcpServers": {
"smartinspector": {
"command": "uv",
"args": ["run", "si-mcp"],
"env": {
"SI_API_KEY": "your-api-key"
}
}
}
}mcp_servers:
- name: smartinspector
command: uv
args:
- run
- si-mcp
env:
SI_API_KEY: your-api-key全量分析管线:collector (Trace 采集 + SQL) → analyzer (LLM 性能解读) → attributor (SI$ → 源码归因) → reporter (Markdown / JSON 报告)
用户在 Perfetto UI 框选时间范围
→ SI Bridge Plugin (WebSocket client)
→ BridgeServer (ws://127.0.0.1:9877/bridge)
→ frame_analyzer agent (查询切片 → 源码归因 → LLM 分析)
→ 结果回传 Perfetto UI 展示(实时进度 + Markdown 报告)
使用 /open 启动自托管 Perfetto UI 后,在时间轴上拖选一段范围,点击右侧 SI Frame Analysis 面板中的 Analyze with SI Agent 按钮。分析过程中实时显示查询进度、源码归因工具调用(Glob/Grep/Read)和 LLM 分析状态,最终在面板中展示 Markdown 格式的帧分析报告。
/frame ts=X dur=YCLI 直接分析指定时间范围- 插件自动重连,进度实时推送,归因过程透明可见
使用 perfetto-plugin/build.sh 构建包含 SI Bridge 插件的自托管 Perfetto UI:
前置条件: Node.js >= 18、npm、git
# 首次构建(clone Perfetto + 复制插件 + 编译)
./perfetto-plugin/build.sh
# 后续构建(跳过 clone,仅重新编译)
./perfetto-plugin/build.sh --skip-clone构建脚本会自动完成以下步骤:
- Clone Perfetto 仓库(shallow clone)到
perfetto-build/ - 复制 SI Bridge 插件到 Perfetto 插件目录
- 在
default_plugins.ts中注册插件 - 执行
ui/build编译(含依赖安装、TypeScript 编译、WASM)
构建产物输出到 perfetto-build/ui/out/dist/,可通过 /open 命令启动自托管 Perfetto UI。
注意: 脚本会自动移除 PATH 中的 Android NDK
strip以避免 macOS 上 Mach-O arm64 兼容性问题。如需代理,请提前设置http_proxy/https_proxy。
全链路异常处理,确保单节点失败不影响整体会话:
REPL 主循环 ─── 全局 try/except,异常后保留 state 继续输入
└── graph.stream() ─── try/except,异常后打印 [error] 不崩溃
└── orchestrator LLM ─── try/except,失败走 fallback
└── 各节点 ─── node_error_handler 装饰器统一捕获
详细架构见 ARCHITECTURE.md。
维度注册体系提供插件式架构,将性能分析能力拆分为独立的、自包含的分析维度。每个维度封装了从 SQL 采集到预计算结论的完整逻辑。
架构:
AnalysisDimension (ABC)
├── collect(tp) → dict # SQL 查询采集
├── compute_hint(data, ctx) # 确定性预计算(不调用 LLM)
├── format_section(data) # Markdown 格式化(供 LLM 消费)
├── metric_filter(data) # Metric QA 数据过滤
├── skill_name # 关联的专家知识文件
└── metric_triggers # 自然语言触发词
已注册维度(7 个内置维度):
| 维度 | SQL 数据源 | Hint 触发条件 | Metric 触发词 |
|---|---|---|---|
lock_contention |
__intrinsic_thread_state (futex) |
主线程 >5ms,其他 >10ms | 锁竞争/lock/futex |
sched_latency |
sched.runnable stdlib 模块 |
平均延迟 > 帧预算 50% | 调度延迟/runnable |
gc_events |
slice (GC/GarbageCollector) |
pause >10ms 或超过帧预算 | gc/垃圾回收 |
file_io |
__intrinsic_thread_state (io_wait) |
主线程 IO >5ms | 文件io/磁盘 |
memory_trend |
process_counter_track (mem.rss) |
RSS 增长 >20% | 内存趋势/内存泄漏 |
binder_ipc |
__intrinsic_thread_state (binder) |
主线程 binder 等待 >10ms | binder/ipc/跨进程 |
cpu_throttling |
cpu_counter_track + counter |
平均频率 < 最大频率 50% | 降频/throttling |
扩展新维度:
- 创建
src/smartinspector/collector/dimensions/<name>.py - 继承
AnalysisDimension,用@register_dimension装饰 - 实现
collect()方法(必需),可选实现compute_hint()/format_section()/metric_filter() - 添加专家知识到
prompts/skills/dimensions/<name>.md - 下次流水线运行时自动发现(
DimensionRegistry.discover())
Prompt Skill 系统将 LLM 指令与领域知识分离,实现按需加载:每个 Agent 只注入其所需的专业知识,避免无关上下文干扰。
目录结构:
prompts/
├── *.txt # LLM 指令模板(行为定义)
└── skills/
├── SKILL.md # Skill 索引
├── shared/ # 共享知识(所有 Agent 共用)
│ ├── si-tag-system.md # SI$ 标签体系说明
│ └── search-strategy.md # 源码搜索策略
└── dimensions/ # 维度专家知识(按需注入)
├── lock-contention.md # 锁竞争分析知识
├── cpu-scheduling.md # CPU 调度分析知识
├── cpu-throttling.md # 降频分析知识
├── gc-analysis.md # GC 分析知识
├── io-analysis.md # IO 分析知识
├── memory-analysis.md # 内存分析知识
├── binder-ipc.md # Binder IPC 分析知识
├── startup.md # 启动分析知识
└── ui-jank.md # UI 卡顿分析知识
API:
| 函数 | 用途 |
|---|---|
load_prompt(name) |
加载 prompts/{name}.txt 指令模板 |
load_skill(name, category) |
加载 prompts/skills/{category}/{name}.md 知识文件(缓存) |
load_prompt_with_skills(name, *skills) |
加载指令 + 追加多个 skill 知识 |
Skill 引用格式:
"gc-analysis"→prompts/skills/dimensions/gc-analysis.md"shared:si-tag-system"→prompts/skills/shared/si-tag-system.md
设计原则:
- 知识/指令分离:指令(
.txt)定义 Agent 行为规则,知识(.md)提供领域事实 - 按需加载:Agent 根据当前分析任务动态组合需要的知识文件
- 维度关联:每个维度通过
skill_name属性自动关联对应的专家知识
| 平台 | 状态 | Trace 采集 | 方法 Hook | 源码归因 |
|---|---|---|---|---|
| Android | 已实现 | Perfetto + adb | Pine AOP | 支持 |
| HarmonyOS | 规划中 | hdc + hiperf/hitrace | — | — |
| iOS | 规划中 | Instruments + Xcode | — | — |
- Trace 采集:Perfetto (ftrace + atrace + CPU callstack + Java heap + 系统级 CPU + 11 个 stdlib 模块 + 7 个维度注册模块)
- 方法 Hook:Pine AOP 框架,运行时 hook Activity/Fragment/RecyclerView 等框架方法
- 卡顿检测:BlockMonitor (BlockCanary-style),监测主线程每条 Message 耗时,容量限制防 OOM
- 通信:WebSocket (adb reverse),CLI ↔ App 实时配置同步 + 数据传输
- Ping/Pong 心跳检测僵尸连接
- 配置下发带 msg_id + ACK 确认
- WS server ready event 防止启动竞态条件
- WS server 启动异常不再静默吞掉
- Release 变体:纯 no-op stubs,编译器内联后零运行时开销
- Hook 安全:嵌套深度保护防 atrace 溢出,Tag 超 127 字节自动截断
- Trace 采集:hdc + hiperf/hitrace
- 方法 Hook:待定
- 已有 prompt 模板:
reference-hdc-commands.txt
smartinspector/
├── src/smartinspector/ # Python CLI + Agent
│ ├── cli.py # CLI 入口 (argparse)
│ ├── graph/ # LangGraph 编排 (模块化包)
│ │ ├── __init__.py # 公共导出 (create_graph, run_graph, main)
│ │ ├── builder.py # LangGraph 图构建 (节点+边+条件路由)
│ │ ├── cli.py # CLI REPL 主循环 (prompt_toolkit, Tab补全, 全局异常保护)
│ │ ├── state.py # AgentState + RouteDecision + pass-through
│ │ ├── streaming.py # 图流式执行 (_stream_run, MemorySaver, 错误处理)
│ │ └── nodes/ # LangGraph 图节点
│ │ ├── orchestrator.py # 路由分类 + fallback (few-shot, 异常处理)
│ │ ├── android.py # Android Expert (trace 采集+分析)
│ │ ├── analyzer.py # 性能分析 (perf_analyzer_node + analyzer_node)
│ │ ├── explorer.py # 源码搜索 (grep/glob/read)
│ │ ├── collector.py # 设备 trace 采集 (PerfettoCollector, WS+SQL block events 合并)
│ │ ├── attributor.py # 源码归因 (SI$ slice → 源码定位, 结构化输出)
│ │ └── reporter/ # 报告生成
│ │ ├── __init__.py # reporter_node 入口 (流式输出)
│ │ ├── generator.py # LLM 报告生成 (流式+重试)
│ │ ├── formatter.py # 数据格式化 (perf+归因→Markdown)
│ │ ├── json_formatter.py # JSON 结构化报告格式化
│ │ └── persistence.py # 报告文件保存
│ │
│ ├── agents/ # Agent 定义 (LLM + Tools)
│ │ ├── android.py # Android Expert Agent
│ │ ├── explorer.py # Code Explorer Agent
│ │ ├── perf_analyzer.py # Perf Analyzer (单次 LLM 调用 + 验证重试)
│ │ ├── attributor.py # 源码归因 Agent (run_attribution)
│ │ ├── frame_analyzer.py # 帧分析 Agent (Perfetto UI 交互归因)
│ │ ├── deterministic.py # 确定性预计算 + SQL Summarizer (减少 LLM token)
│ │ └── verifier.py # 分析质量验证 (L1 格式 + L2 一致性, 0 token)
│ │
│ ├── collector/perfetto.py # PerfettoCollector (adb→SQL→JSON, CPU调用链, 系统级CPU, 11 stdlib modules, 7 维度注册, context manager)
│ ├── collector/dimensions/ # 维度注册体系 (插件式分析维度)
│ │ ├── __init__.py # DimensionRegistry + @register_dimension
│ │ ├── base.py # AnalysisDimension ABC + HintContext
│ │ ├── lock_contention.py # 锁竞争维度 (futex)
│ │ ├── sched_latency.py # 调度延迟维度
│ │ ├── gc_events.py # GC 事件维度
│ │ ├── file_io.py # 文件 IO 维度
│ │ ├── memory_trend.py # 内存趋势维度
│ │ ├── binder_ipc.py # Binder IPC 维度
│ │ └── cpu_throttling.py # CPU 降频维度
│ ├── collector/startup.py # 冷启动分析器 (启动阶段切分, 关键路径提取, 瓶颈识别)
│ ├── collector/memory.py # 内存分配分析器 (heap_graph, 泄漏检测, 内存趋势)
│ ├── headless.py # Headless/CI 非交互式运行器 (全量流水线, JSON/Markdown 输出)
│ ├── storage/store.py # 报告存储层 (基线管理, 历史查询, 对比数据源)
│ ├── commands/ # Slash 命令 (注册表模式)
│ │ ├── __init__.py # 命令注册表 (handle_slash_command)
│ │ ├── attribution.py # SI$ tag 解析 + 归因提取
│ │ ├── device.py # 设备管理 (/devices, /connect)
│ │ ├── hook.py # Hook 配置 (/config, /hooks)
│ │ ├── orchestrate.py # 编排命令 (/full, /report)
│ │ ├── session.py # 会话管理 (/help, /clear)
│ │ └── trace.py # Trace 采集 (/trace, /record, /open, /close, /frame)
│ │
│ ├── tools/ # LangChain 工具 (grep/glob/read/perfetto)
│ │ └── path_utils.py # 共享路径校验 (防目录遍历)
│ ├── ws/server.py # WebSocket Server (心跳检测, ready event, 动态端口)
│ ├── ws/bridge_server.py # Perfetto UI Bridge Server (自托管 UI + WS 桥接)
│ ├── prompts.py # Prompt 文件加载器
│ ├── config.py # 全局配置 (LLM 模型, source dir, hook config 持久化, 环境变量覆盖)
│ ├── token_tracker.py # LLM Token 使用量追踪
│ └── perfetto_compat.py # macOS IPv4 兼容修复
│
├── platform/ # 平台 SDK
│ └── android/tracelib/ # Android SDK (AAR)
│ └── src/main/java/.../tracelib/
│ ├── TraceHook.java # Pine AOP 方法 hook (深度保护, Tag截断, 系统widget过滤)
│ ├── ComposeHook.kt # Compose 重组追踪 (TracerImpl hook, API 31+)
│ ├── BlockMonitor.java # 主线程卡顿检测 (容量限制防OOM, Fragment泄漏修复)
│ ├── SIClient.java # WebSocket 客户端
│ ├── HookConfig.java # 配置模型 (JSON 序列化, BuildConfig.DEBUG守卫)
│ └── HookConfigManager.java # 配置管理 (SP 持久化)
│
├── perfetto-plugin/ # Perfetto UI SI Bridge 插件
│ ├── com.smartinspector.Bridge/ # 插件源码 (TypeScript)
│ └── build.sh # 构建脚本 (clone Perfetto + 复制插件 + build)
│
├── prompts/ # LLM Prompt 模板
│ ├── *.txt # 指令模板 (attributor, report-generator, perf-analyzer 等)
│ └── skills/ # Skill 知识文件 (按需加载)
│ ├── SKILL.md # 索引文件
│ ├── shared/ # 共享知识 (SI$ 标签, 搜索策略)
│ └── dimensions/ # 维度专家知识 (9 个 .md 文件)
├── bin/ # trace_processor_shell
├── reports/ # 生成的性能报告 (Markdown)
├── tests/ # 单元测试
├── Dockerfile # 多阶段 Docker 构建 (si-analyzer / si-mcp)
├── docker-compose.yml # Docker Compose (ci/dev/mcp/prod profiles)
└── docker/healthcheck.sh # 容器健康检查脚本
SDK 通过 Pine AOP 框架 hook 框架方法,用 SI$ 前缀的 Trace.beginSection 标记用户代码调用,Perfetto atrace 采集后由 CLI 分析。
| Hook | 默认 | Tag 格式 | 说明 |
|---|---|---|---|
| Activity Lifecycle | ON | SI$ActivityClass.onCreate |
Activity 生命周期 |
| Fragment Lifecycle | ON | SI$FragmentClass.onCreateView |
Fragment 生命周期 (AndroidX + app) |
| RV Pipeline | ON | SI$RV#[viewId]#[Adapter].dispatchLayoutStep2 |
RecyclerView 管线 |
| RV Adapter | ON | SI$RV#[viewId]#[Adapter].onBindViewHolder |
Adapter 数据绑定 |
| Layout Inflate | OFF | SI$inflate#[layout]#[parent] |
布局加载 |
| View Traverse | OFF | SI$view#[ViewClass].measure |
View measure/layout/draw |
| Handler Dispatch | OFF | SI$handler#[msgClass] |
Handler 消息分发 |
| Block Monitor | ON | SI$block#[MsgClass]#[dur]ms |
主线程卡顿检测 (≥100ms) |
| Network IO | ON | SI$net#[Class].execute |
OkHttp / HttpURLConnection |
| Database IO | ON | SI$db#[Class].query#[table] |
SQLiteDatabase / Room |
| Image Load | ON | SI$img#[Class].into |
Glide / Coil |
| Compose Recomposition | ON | SI$compose#[Composable]#recompose |
Compose 重组追踪 (API 31+) |
IO Hook 说明:Network/DB/Image hook 在所有线程执行,使用独立前缀 (SI$net#/SI$db#/SI$img#),Python 端单独收集到 io_slices,不污染主线程 view_slices 分析。
Trace → SI$ slices → 过滤系统类 → 提取 class+method → Glob→Grep→Read 搜索源码 → LLM 归因
归因系统通过两层过滤排除系统/框架代码:
- FQN 包名匹配:
android.*、androidx.*、java.*等 - 短类名模式匹配:
Choreographer、FragmentManager、ViewRootImpl等(Perfetto atrace 截断 FQN 时)
uv run smartinspector --ci [选项]| 参数 | 说明 |
|---|---|
--ci |
启用非交互式 CI 模式 |
--trace <path> |
指定已有 trace 文件(跳过设备采集) |
--target <package> |
目标进程包名 |
--duration <ms> |
采集时长(默认 10000ms) |
--output <path> |
输出文件路径 |
--format markdown|json |
报告格式(默认 markdown) |
--src <path> |
源码目录 |
--debug |
启用 debug 日志 |
| 命令 | 说明 |
|---|---|
/full [--no-wait] |
全量分析流水线 (采集→分析→归因→报告)。--no-wait 跳过等待 App 连接,适用于冷启动耗时分析 |
/quick |
快速分析(纯确定性,不调用 LLM,秒级完成)。无 API Key 时自动降级 |
/compare <r1> <r2> |
对比两份报告,生成 before/after 趋势报告 |
/trace [duration_ms] [pkg] |
采集 + 自动分析 Perfetto trace |
/record [duration_ms] [pkg] |
只采集不分析,返回 .pb 文件路径 |
/analyze [path] |
分析 trace 文件(无参数时分析上次采集结果) |
/frame ts=X dur=Y |
分析指定时间范围的帧(ts/dur 为纳秒,CLI 直接分析) |
/open [path] |
启动 Perfetto UI + Bridge Server,交互式框选帧分析 |
/close |
关闭 Perfetto UI Bridge Server |
/report [path] |
生成性能报告(可选输出到文件) |
/config |
查看当前 hook 配置(通过 WS 从 App 获取) |
/config <json> |
推送 JSON 配置到 App(如 {"rv_adapter": false}) |
/config reset |
恢复 hook 默认配置 |
/config source_dir <path> |
设置源码目录(自动持久化) |
/hooks |
查看所有 hook 点开关状态 |
/hook on <hook_id> |
开启指定内置 hook 点(如 layout_inflate) |
/hook off <hook_id> |
关闭指定内置 hook 点 |
/hook add <class> <method> |
添加自定义 hook 点 |
/hook rm <class> |
删除自定义 hook 点 |
/devices |
列出已连接 adb 设备 |
/connect <host:port> |
通过 adb TCP 连接设备 |
/disconnect |
断开 TCP 设备连接 |
/status |
查看当前会话状态(WS 连接、perf 数据等) |
/summary |
查看 perf_summary 摘要 |
/tokens |
查看 token 使用量 |
/clear |
清除所有分析状态和对话 |
/debug |
打开设备端 Hook 调试配置面板 |
/help |
帮助信息(支持 Tab 补全) |
Orchestrator 通过 LLM 分类将用户请求路由到对应 Agent:
- 全面分析 (
full_analysis): "全面分析列表滑动性能" / "分析冷启动耗时" / "测一下应用启动时间" / "冷启动性能怎么样" → collector → analyzer → attributor → reporter - 平台采集 (
android): "采集 trace 分析 FPS" / "采集一下 trace" / "帮我看看 CPU 和内存指标" → Platform Expert Agent - 性能解读 (
analyze): "解读这份数据" / "分析一下刚才采集的数据" / "解读一下这个 perf_summary" → Perf Analyzer - 源码搜索 (
explorer): "搜索 XXX 类源码" / "查看 LazyForEach 的实现" / "定位 DataManager.loadData 方法" → Code Explorer - 通用问答 (
end): "什么是卡顿" / "怎么优化列表滑动" / "你好" → Fallback 回复 - 指标追问 (
metric_qa): "CPU 占用率怎么样" / "帧率怎么样" / "内存有没有泄漏" / "性能怎么样" → Metric QA(需要先完成分析)
在已有 perf_summary 数据的基础上,用自然语言追问具体性能指标:
| 类别 | 指标 ID | 触发词 |
|---|---|---|
| CPU | cpu, cpu_hotspot, sched, blocked |
cpu占用/热点/调度/阻塞 |
| 内存 | memory, heap |
内存/RSS/堆/泄漏 |
| UI | frame, rv, view, compose, inflate, startup |
帧率/列表/绘制/重组/布局/启动 |
| IO | io, network, db, image |
io/网络/数据库/图片 |
| 系统 | thread_state, sys, input |
线程状态/系统/触摸 |
| 维度 | lock_contention, sched_latency, gc_events, file_io, memory_trend, binder_ipc, cpu_throttling |
锁竞争/调度延迟/GC/文件IO/内存趋势/Binder/降频 |
| 总览 | overview |
性能总览 |
前置条件:必须先通过
/full、/trace、/analyze等命令完成分析。
全量分析流水线(/full、/full --no-wait 或自然语言触发 full_analysis)会生成 Markdown 性能报告,保存到 reports/ 目录。以下为实际生成的报告摘要:
## 问题列表
**源码归因结果共包含6条记录,已全部生成对应问题条目。**
### P0 CpuBurnWorker 主线程执行CPU密集型计算导致卡顿
**现象**:`CpuBurnWorker.startMainThreadWork$run` 在主线程执行耗时 145.00ms。该方法在主线程循环执行100,000次 `Math.sqrt` 计算,是导致主线程卡顿的直接原因。
**原因**:根据源码归因,该方法是CPU烧录测试代码,在主线程上执行密集的数学运算,每次循环约5ms,每200ms执行一次,严重阻塞了主线程的UI渲染。
**调用链**:`CpuBurnWorker.startMainThreadWork$run 145ms`
**位置**:`app/src/main/java/com/smartinspector/hook/worker/CpuBurnWorker.kt:41-49`
**建议**:
1. **移除或禁用测试代码**:在正式发布版本中,应移除或禁用此类用于测试的CPU烧录代码。
2. **移至后台线程**:如果该逻辑是应用功能所需,必须将其移至后台线程(如使用 `CoroutineScope(Dispatchers.Default).launch` 或 `ExecutorService`)执行,避免阻塞主线程。
3. **降低计算频率和强度**:如果必须在主线程执行,应大幅减少循环次数(例如从100,000次减少到1,000次以内)或延长执行间隔。
### P0 DemoAdapter.onBindViewHolder 存在多项耗时操作导致列表滑动卡顿
**现象**:`DemoAdapter.onBindViewHolder` 单次调用最高耗时 74.95ms,在测试期间共调用7次,累计耗时 202.29ms。该方法是导致帧#111严重卡顿(267.25ms)和 RecyclerView `dispatchLayoutStep2` 耗时 229.07ms 的主要原因。
**原因**:根据源码归因,该方法内存在多个阻塞主线程的耗时操作:
1. `doExpensiveWork()` 中调用了 `Thread.sleep(20)` 进行强制等待。
2. `repository.loadItemsSync(5)` 进行同步数据加载。
3. 执行了30次字符串拼接循环。
4. 进行了 `Bitmap` 解码操作。
**调用链**:`LinearLayoutManager.onLayoutChildren 228.97ms → RV OnBindView 75.05ms → DemoAdapter.onBindViewHolder 74.95ms`
**位置**:`app/src/main/java/com/smartinspector/hook/adapter/DemoAdapter.java:40-64`
**建议**:
1. **移除 Thread.sleep**:在主线程中绝对禁止使用 `Thread.sleep()`,应立即移除。
2. **异步加载数据**:将 `repository.loadItemsSync(5)` 改为异步加载(如使用 `LiveData`、`RxJava` 或 `Coroutine`),在数据准备好后再通知 `Adapter` 更新。
3. **优化字符串构建**:使用 `StringBuilder` 替代多次 `+` 操作进行字符串拼接。
4. **异步加载与缓存图片**:将 `Bitmap` 解码移至后台线程,并使用 `Glide`、`Picasso` 等图片加载库进行异步加载和缓存,避免每次绑定都解码。
### P1 MainActivity.onCreate 中延迟任务过多且存在潜在风险
**现象**:`MainActivity.onCreate` 耗时 14.67ms。方法中启动了多个 `Handler.postDelayed` 任务。
**原因**:根据源码归因,方法中启动了多个延迟任务:1) 5秒后加载数据,2) 500ms间隔的循环padding调整,3) 8秒后显示详情Fragment。过多的延迟任务可能阻塞主线程,500ms的循环任务可能造成不必要的性能开销,且使用 `Handler.postDelayed` 有潜在的内存泄漏风险。
**调用链**:`MainActivity.onCreate 14.67ms`
**位置**:`app/src/main/java/com/smartinspector/hook/MainActivity.java:31-67`
**建议**:
1. **合并或优化任务**:评估500ms循环任务的必要性,考虑是否可以合并或由事件驱动(如监听视图状态)来触发。
2. **使用 View.post**:对于需要在主线程执行的延迟UI操作,优先使用 `View.post()` 或 `View.postDelayed()`,这可以自动处理 `View` 生命周期,降低内存泄漏风险。
3. **使用 Lifecycle-aware 组件**:对于需要在特定生命周期执行的任务,考虑使用 `Lifecycle` 和 `Coroutine` 等现代架构组件来管理。
### P1 DemoAdapter.onCreateViewHolder 加载复杂布局耗时
**现象**:`DemoAdapter.onCreateViewHolder` 单次调用最高耗时 4.89ms,在测试期间共调用7次,累计耗时 10.49ms。
**原因**:根据源码归因,该方法加载了复杂布局 `item_complex`。布局的复杂度直接影响 `inflate` 和后续测量、布局的速度。
**调用链**:`DemoAdapter.onCreateViewHolder 4.89ms`
**位置**:`app/src/main/java/com/smartinspector/hook/adapter/DemoAdapter.java:33-37`
**建议**:
1. **检查并简化布局**:使用 Layout Inspector 或 `ConstraintLayout` 的布局优化工具,检查 `item_complex.xml` 的层级,减少不必要的嵌套。
2. **使用 ViewStub**:对于列表中并非立即显示的复杂部分,可以考虑使用 `ViewStub` 进行延迟加载。
3. **启用视图复用**:确保 `RecyclerView` 和 `Adapter` 正确设置了 `setHasStableIds(true)` 并实现了 `getItemId()`,以优化视图复用。
### P1 item_complex.xml 布局嵌套过深导致inflate耗时
**现象**:`item_complex.xml` 的 inflate 操作单次最高耗时 4.77ms,在测试期间共执行7次,累计耗时 9.80ms。
**原因**:根据源码归因,该布局有4层嵌套,并且包含自定义视图 `HeavyDrawView`。深层级的嵌套会导致测量和布局过程计算量增大。
**调用链**:`inflate#item_complex 4.77ms`
**位置**:`app/src/main/res/layout/item_complex.xml:1-64`
**建议**:
1. **使用 ConstraintLayout 扁平化布局**:将根布局替换为 `ConstraintLayout`,利用其约束关系减少嵌套层级,目标是控制在2层以内。
2. **优化 HeavyDrawView**:分析 `HeavyDrawView` 的 `onDraw` 方法,确保其绘制操作高效,避免在 `onDraw` 中分配对象或进行复杂计算。
3. **使用 merge 标签**:如果该布局被 `include`,考虑在根节点使用 `<merge>` 标签以消除一层冗余的 `ViewGroup`。
## 附录
**采集工具**:Smart Inspector
**原始数据位置**:`/var/folders/tb/6pgk76d11bd278v01zfqkq540000gn/T/tmpatm5lr_x.pb`
[reporter] Report generated
[reporter] Report saved to /xx/xx/reports/perf_report_20260415_232256.md (7.8KB)
Token usage:
Stage Input Output Total Calls
------------------------------------------------------
orchestrator 456 3 459 1
perf_analyzer 2.9k 415 3.3k 1
attributor 59.1k 3.3k 62.4k 24
reporter 3.1k 1.3k 4.4k 1
------------------------------------------------------
TOTAL 65.6k 5.0k 70.6k 27
| 组件 | 技术 |
|---|---|
| Agent 编排 | LangGraph + LangChain |
| LLM | DeepSeek / Claude / OpenAI (通过 SI_MODEL 配置) |
| Android Trace | Perfetto + atrace (ftrace + CPU callstack + Java heap) |
| HarmonyOS Trace | hiperf + hitrace (规划) |
| 方法 Hook (Android) | Pine AOP Framework |
| CLI 交互 | prompt_toolkit (Tab 补全, REPL) + argparse (CI 模式) |
| 通信 | WebSocket (CLI ↔ App, 心跳检测, 动态端口) |
| Trace 分析 | trace_processor_shell (SQL, v55.1 multi-arch) |
| 容器化 | Docker multi-stage build (AMD64/ARM64) |
| 状态管理 | LangGraph MemorySaver (get_state) |
通过 .env 文件或环境变量配置 LLM 提供商:
cp .env.example .env| 变量 | 说明 | 默认值 |
|---|---|---|
SI_MODEL |
全局默认模型 | deepseek-chat |
SI_BASE_URL |
API Base URL (OpenAI 兼容) | https://api.deepseek.com |
SI_API_KEY |
API Key (回退到 OPENAI_API_KEY) |
— |
SI_ATTRIBUTOR_MODEL |
归因 Agent 模型覆盖 (代码理解) | 同 SI_MODEL |
SI_TOOL_TIMEOUT |
工具子进程超时 (grep/glob) | 30 |
SI_READ_MAX_LINES |
Read 工具最大返回行数 | 2000 |
SI_READ_MAX_BYTES |
Read 工具最大返回字节数 | 51200 |
SI_READ_MAX_LINE_LENGTH |
Read 工具单行最大字符数 | 2000 |
SI_REPORT_MAX_TOKENS |
报告生成最大输入 token | 4000 |
SI_WS_PING_TIMEOUT |
WebSocket ping 超时 (秒) | 30 |
切换到 Claude 示例:
SI_MODEL=claude-sonnet-4-20250514
SI_BASE_URL=https://api.anthropic.com
SI_API_KEY=sk-ant-xxx归因用更强模型示例:
SI_MODEL=deepseek-chat
SI_ATTRIBUTOR_MODEL=claude-sonnet-4-20250514归因环节需要代码理解能力,建议使用更强的模型。其他环节(路由、报告)用 DeepSeek 即可。
- Python 3.12+
- macOS / Linux / Windows (通过 Docker)
- Android: 设备 API 28+,开启 USB 调试,adb 已加入 PATH
- HarmonyOS: hdc 已加入 PATH (规划)
- iOS: Xcode + Instruments (规划)
SmartInspector 提供多阶段 Docker 构建,支持 AMD64 和 ARM64 架构,内置 Perfetto v55.1 trace_processor_shell,可直接在 CI/CD 环境中运行。
# 默认构建 (analyzer 镜像)
docker build -t smartinspector:latest .
# 指定目标
docker build --target si-analyzer -t smartinspector:analyzer .
docker build --target si-mcp -t smartinspector:mcp .
# ARM64 平台构建
docker build --build-arg TARGETARCH=arm64 -t smartinspector:arm64 .提供四种运行 Profile,按场景选择:
| Profile | 用途 | 命令 |
|---|---|---|
ci |
CI/Headless 分析 | docker compose --profile ci run --rm si-analyzer smartinspector --ci ... |
dev |
开发环境(挂载源码,暴露 WS 端口) | docker compose --profile dev up |
mcp |
MCP Server(stdio transport) | docker compose --profile mcp up -d si-mcp-server |
prod |
生产环境(资源限制 + 日志轮转) | docker compose --profile prod up -d |
# 1. 配置环境变量
cp .env.docker.example .env
# 编辑 .env 填入 SI_API_KEY
# 2. 分析已有 trace 文件,输出 JSON 报告
docker compose --profile ci run --rm \
-e SI_API_KEY=$SI_API_KEY \
si-analyzer \
smartinspector --ci --trace /traces/trace.pb --format json --src /source
# 3. 生成 Markdown 报告到文件
docker compose --profile ci run --rm \
-e SI_API_KEY=$SI_API_KEY \
si-analyzer \
smartinspector --ci --trace /traces/trace.pb --output /app/reports/report.md| 宿主机路径 | 容器路径 | 用途 |
|---|---|---|
${TRACE_DIR:-./traces} |
/traces |
Trace 文件输入(只读) |
./reports |
/app/reports |
报告输出 |
${SOURCE_DIR:-./src} |
/source |
源码目录(归因用,只读) |
python:3.12-slim (builder)
└── uv install dependencies → /opt/venv
└── si-analyzer (runtime)
├── /opt/venv (Python dependencies)
├── /app/bin/trace_processor_shell (Perfetto v55.1, multi-arch)
├── /app/src/smartinspector/ (application code)
├── /app/prompts/ → /opt/venv/lib/python3.12/prompts (symlink)
└── ENTRYPOINT ["smartinspector"]
└── si-mcp (extends si-analyzer)
└── ENTRYPOINT ["si-mcp"]
| # | 项目 | 说明 | 状态 |
|---|---|---|---|
| P1-1 | Compose 重组追踪 | 追踪 Jetpack Compose 重组次数和耗时,定位不必要的 recomposition | ✅ 已完成 |
| P1-2 | 内存分配分析 | 基于 heap_graph 数据源分析内存分配热点,定位内存抖动和泄漏 |
✅ 已完成 |
| P1-3 | 历史对比与趋势 | 多次分析结果对比,生成 before/after 报告和性能趋势图 | ✅ 已完成 |
| P1-4 | 智能一键分析 | 纯确定性快速分析,不调用 LLM,30 秒内完成轻量分析 | ✅ 已完成 |
| P1-5 | ExtraHook 参数自动推断 | 自动推断所有重载签名,无需手动配置方法参数 | ✅ 已完成 |
| P1-6 | SQL Summarizer | 压缩 SQL 查询结果为统计摘要+异常采样,降低 60-80% token 消耗 | ✅ 已完成 |
| P1-7 | Analysis Verifier | L1 格式检查 + L2 一致性验证,自动检测遗漏和不一致,支持重试 | ✅ 已完成 |
- HarmonyOS collector (hdc + hiperf/hitrace)
- iOS Instruments 集成
- Native C/C++ 代码覆盖
- Docker 容器化部署 (multi-stage build, AMD64/ARM64, CI/CD 集成)
- 帧严重度阈值区分刷新率 (120Hz 设备帧预算 8.33ms)
- 输入事件关联 (touch event → frame jank 因果)
- RV Instance 区分 create vs bind 开销
- Perfetto
android.surfaceflinger.frame维度 (CPU vs GPU 瓶颈) - 自适应阈值 (基于设备能力动态调整)
thread_state N+1 查询优化→ 已完成:重写为__intrinsic_thread_state表,支持blocked_function/io_wait/waker_utid- LLM 实例统一管理 (LLMFactory)
P1-1: Compose 重组追踪
ComposeHook.kt: Hook Compose Runtime 的TracerImpl和startRestartGroup/endRestartGroup- 切片前缀
SI$compose#,Tag 格式:SI$compose#ComposableName#recompose/SI$compose#ComposableName#first - Python 端新增
collect_compose_slices()查询和重组分析
P1-2: 内存分配分析
collector/memory.py:MemoryAnalyzer基于heap_graph表分析 Java 堆内存- 按类名聚合对象数量和总大小,检测 Activity/Fragment 泄漏嫌疑
- 内存增长趋势追踪(RSS / anon 随时间变化)
P1-3: 历史对比与趋势
commands/compare.py:/compare命令,多次分析结果对比storage/store.py: 报告存储层,支持基线管理和历史查询- 生成 before/after 报告,自动标注回归项和改善项
P1-4: 智能一键分析
commands/quick.py:/quick命令,纯确定性快速分析(不调用 LLM)- 仅运行 fast-path 归因 +
compute_hints,秒级完成 - 无 API Key 时自动降级为 quick 模式
P1-5: ExtraHook 参数自动推断
TraceHook.java改进hookExtraClasses():自动推断所有重载签名- 遍历
getDeclaredMethods()匹配方法名,替代原先的只尝试无参签名
P1-6: SQL Summarizer
deterministic.py新增summarize_sql_result()— 将 SQL 查询结果压缩为统计摘要 (count/min/max/avg/p95/p99) + 分布直方图 + 异常采样 + 去重聚合deterministic.py新增compress_perf_json()— 对 perf JSON 中的大列表字段 (slowest_slices/block_events/frame_timeline/thread_state) 自动应用压缩- 集成到
perf_analyzer.py(perf_json 传入前压缩) 和frame_analyzer.py(slices 列表压缩) - Token 消耗降低 60-80%,减少 LLM 在大量数据中的幻觉
P1-7: Analysis Verifier
agents/verifier.py新增分层验证系统 (0 token,纯规则)- L1 格式检查:数值存在性、方法名引用、长度合理、P0/P1/P2 分级
- L2 一致性验证:P0 问题覆盖、关键数据点数值一致性 (±20%)、热点方法覆盖
- 集成到
perf_analyzer.py和frame_analyzer.py,L2 失败时自动重试一次补充遗漏 VerificationResult包含 score/issues/warnings/l1_passed/l2_passed 属性
P0-1: IO Hooks 启用
- Network/DB/Image IO Hook 默认开启
- IO 切片独立收集到
io_slices,不污染主线程view_slices分析 collect_io_slices()方法从所有线程收集SI$net#/SI$db#/SI$img#切片
P0-2: 冷启动专项分析
collector/startup.py:StartupAnalyzer将启动序列切分为 4 个阶段- pre-main (进程启动 → Application.attachBaseContext)
- Application.onCreate → first Activity.onCreate
- Activity.onCreate → 首帧 doFrame
- 首帧渲染
graph/nodes/startup.py: 图节点集成,输出 Markdown 格式的启动分析报告- 关键路径提取 + 瓶颈识别 + 自动优化建议
P0-3: Headless/CI 模式
headless.py:HeadlessRunner非交互式运行全量分析流水线- CLI 参数:
--ci启用,--trace/--target/--duration/--output/--format/--debug - 支持 Markdown 和 JSON 两种输出格式
- 无 API Key 时降级为纯确定性分析(跳过 LLM)
P0-4: JSON 报告格式
graph/nodes/reporter/json_formatter.py: 结构化 JSON 报告- 包含
summary(FPS/CPU/jank)、issues(P0/P1/P2 分级)、metrics(详细指标) - 自动关联 attribution 结果到 issue 的
source字段 - 适合 CI/CD 自动化解析
P0-5: IO 切片归因
agents/attributor.py支持 IO 类型切片(SI$net#/SI$db#/SI$img#)归因commands/attribution.py解析 IO tag 提取 class/method 用于源码搜索- 归因结果包含
io_type字段(network/database/image)
Collector 采集层
- 修复内存数值单位错误(/1024 转换问题)
- 修复 Block Events 数据覆盖(WS+SQL 合并)
- CPU 热点添加调用链重建
- sched 添加阻塞原因分析
- 新增系统级 CPU 指标采集
- HookConfig 透传 + Tag 截断保护
- PerfettoCollector 支持 context manager 协议
Agents 编排层
- Orchestrator LLM 调用异常处理
- REPL 主循环全局异常保护
- graph.stream 循环防崩溃
- node_error_handler 统一节点错误处理
- 路由支持 enum 和 string 双模式
- 路由 prompt few-shot 提升准确率
- 路由 LLM max_tokens=5 减少 token 浪费
- Reporter 输入 token 估算和截断
- Attributor 消息窗口裁剪防 O(n²) 增长
- Fallback 消息窗口过滤仅 Human/AI
- Reporter 真正流式输出防重复打印
- 用 get_state()+MemorySaver 替代手动 state 重建
- Attributor 结构化输出 + 文本解析 fallback
- 清理无引用的 prompts/main.txt
- Agent LLM 单例双重检查锁线程安全
SDK 层
- Release 变体替换为纯 no-op stubs
- PineConfig.debug=true 替换为 BuildConfig.DEBUG
- FragmentLifecycleCallbacks registered 集合内存泄漏修复
- BlockMonitor.blockEvents 容量限制防 OOM
- view_traverse 过滤系统 widget
- SI$ Tag 超 127 字节自动截断
- 高频 hook Log.d BuildConfig.DEBUG 守卫
- Trace 嵌套深度保护防 atrace 溢出
基础设施层
- REPL 全局异常保护
- WS server 启动异常不再静默吞掉
- WebSocket ping/pong 心跳检测
- WS server ready event 防止启动竞态
- streaming graph 迭代错误处理
- state 合并重构为 AgentState 驱动
- 硬编码端口 9876 替换为 get_ws_port()
- Slash 命令 Tab 自动补全
- 版本号从 package metadata 读取
- /clear 清理所有分析状态字段
- 启动前置条件检查 (adb + API key)
- 所有依赖添加版本上限
- /report 支持文件输出
- Hook config 持久化到本地文件
- send_config msg_id + ACK 机制
- 硬编码配置值集中到 config.py,支持环境变量覆盖
- 工具共享路径校验提取到 path_utils 模块
- Collector 全链路异常日志补全
- WS 异常日志替换静默吞掉
