Frame-aligned, dependency-aware scheduling assistant for Android interaction workloads
- 队名:
TracePilot - 成员:
- 潘智勇
- 李松茂
- 邵晨轩
- 贺小轩
- 杨子皓
TracePilot 是一个面向 Android 交互负载的、以帧为对齐单位、具备依赖感知能力的调度辅助系统。
核心路径:在 Pixel 6a 设备上,通过 eBPF 采集调度与进程间依赖事件,利用 Perfetto FrameTimeline 作为 ground truth,在帧窗口内构建依赖关键路径图,识别影响用户体验的关键线程,最终通过安全的用户态 hint 进行受控干预。
- PID 不稳定:同一 App 每次启动 PID 不同,一个 App 可能有多个进程,PID 还会被系统复用
- 卡顿不是单个 PID 的问题:Android jank 的根因通常是 UI thread、RenderThread、Binder、system_server、SurfaceFlinger 之间的等待链
- eBPF 只能观测内核事件,无法直接回答"用户在经历什么"
FrameTimeline 定义问题 → eBPF 提供原因 → Graph 找关键路径 → Hint Engine 做受控干预
eBPF 是 Linux 内核的一项沙箱技术,允许用户在不修改内核源码或加载内核模块的情况下,安全高效地注入自定义程序来观测和控制内核行为。
在本项目中的角色: TracePilot 在 Pixel 6a(Android 14,已 root)上加载 eBPF 探针,通过 kprobe 和 tracepoint 挂载点采集内核调度与进程间通信事件:
| 探针类型 | 采集事件 | 用途 |
|---|---|---|
sched_switch |
线程切换(prev/next TID、运行时长、runnable delay) | 计算线程就绪等待延迟 |
sched_wakeup |
线程唤醒延迟 | 计算 wakeup-to-run latency |
binder_transaction kprobe |
Binder 跨进程调用 | 分析进程间依赖与通信瓶颈 |
futex wait/wake |
锁等待 | 识别锁竞争导致的阻塞 |
cpu_frequency |
CPU 频率与核调度 | 分析大小核负载均衡 |
探针源码位于 ebpf/src/ 目录下,包含多个场景版本:
- 页面切换-基础版:
ebpf/src/页面切换-基础版/bpf/tracepilot.bpf.c - 页面切换-视频浏览增强版:
ebpf/src/页面切换-视频浏览增强版/bpf/tracepilot.bpf.c
探针使用 C 编写,通过 clang 交叉编译为 BPF 字节码(.bpf.o),再由用户态加载器通过 bpf() 系统调用加载到内核。采集的原始事件经 ringbuf 输出到文件(events.bin),供离线分析。
Perfetto 是 Google 开发的 Android/Linux 平台高性能用户态与内核态追踪工具栈,是 Systrace 的继任者。
在本项目中的角色: Perfetto 作为 ground truth(基准事实) 层,用于标定帧边界和识别 jank(掉帧)。
采集配置:
- 以后台守护进程模式运行:
perfetto --background - 128MB ring buffer
- 启用 atrace categories:
gfx、view、am、wm、res、dalvik - 启用 ftrace events:
sched_switch、sched_wakeup、irq、softirq - 采集结束后通过
adb pull拉取.perfetto-trace文件
帧提取:
使用 Perfetto 提供的 trace_processor_shell(预编译的 Linux x86_64 二进制,位于 ebpf/dependencies/perfetto编译工具linux-amd64/)执行 SQL 查询从 trace 中提取帧信息:
beginFrame N vsyncIn Xms→ 帧号 N,期望 VSYNC 时间presentFrameAndReleaseLayers→ 实际显示时间incrementJankyFrames→ 标记 jank 帧
查询结果输出为 frames.txt,包含每帧的帧号、期望 VSYNC 时间、实际显示时间和 jank 标志。
由于 eBPF 探针在 Pixel 6a(ARM64 架构,Android 14) 上运行,开发环境通常为 x86_64,因此采用交叉编译。
方式一:Docker 构建(推荐)
所有编译环境已封装在 Docker 镜像中,无需手动安装 NDK/libbpf:
docker build -t tracepilot-builder .
# 编译全部场景(页面切换、page_turning、camera)
docker run --rm -v .:/workspace tracepilot-builder
# 或只编译特定场景:
docker run --rm -v .:/workspace tracepilot-builder make -C ebpf/src/页面切换-基础版 bpfDocker 镜像包含:
- Ubuntu 22.04 + clang/LLVM/gcc/make
- Android NDK r26b — 交叉编译 aarch64 loader
- libbpf v1.4.7 — 为 aarch64 预编译
libbpf.a - elfutils 0.191 — 为 aarch64 预编译
libelf.a - bpftool — 生成 BPF skeleton
方式二:手动编译(WSL/Ubuntu,不依赖 Docker)
工具链:
- 编译器:Android NDK r26b + clang(target
aarch64-linux-android) - 构建目标:
make bpf→tracepilot.bpf.o(eBPF 字节码)make android→tracepilot-aarch64(ARM64 用户态加载器)
- 部署:
adb push tracepilot-aarch64 /data/local/tmp/+adb push tracepilot.bpf.o /data/local/tmp/
Perfetto 工具链:
Perfetto 官方提供预编译的 Linux 工具链二进制(位于 ebpf/dependencies/perfetto编译工具linux-amd64/),包括:
trace_processor_shell— SQL 查询引擎traced/traced_probes— 追踪守护进程tracebox— 一站式追踪工具traceconv— 格式转换工具
开发机 (x86_64, WSL)
→ NDK clang 交叉编译
→ 生成 ARM64 二进制
→ adb push 到 Pixel 6a (/data/local/tmp/)
→ 加载 eBPF 探针并采集事件
帧对齐是 TracePilot 的核心技术,用于将 eBPF 采集的内核调度事件 与 Perfetto 采集的用户态帧信息 在时间上精确匹配,从而回答"哪些线程导致了哪一帧卡顿"。
对齐流程(三步):
Step 1 — 时间域对齐
eBPF 事件和 Perfetto 帧数据的时间戳均使用设备上的 CLOCK_MONOTONIC,因此两个数据源天然在同一时间域内,无需跨域转换。
Step 2 — 帧窗口匹配 对 Perfetto 提取的每一帧,定义时间窗口:
Frame Window = [expected_VSYNC, actual_presentation_time]
将所有落在此窗口内的 eBPF 调度事件(sched_switch、sched_wakeup)归因到该帧。帧窗口的跨度反映了该帧从期望显示到实际显示的延迟。
Step 3 — 线程聚合与评分 对每帧窗口内的线程,聚合以下指标并打分:
base_score = 0.35 × J + 0.35 × log1p(rd_ms) + 0.15 × log1p(wl_ms) + 0.15 × UI
| 指标 | 含义 |
|---|---|
J = jank_frame_count / num_jank |
该线程参与的 jank 帧占比 |
rd_ms = runnable_delay_p95 |
就绪等待延迟(p95,毫秒) |
wl_ms = wakeup_latency_p95 |
唤醒延迟(p95,毫秒) |
UI |
是否为 RenderThread 或 UI thread |
然后扣除系统开销折扣:
最终得分 = base_score × (1.0 - min(sys_overhead_ratio, 0.9))
噪声过滤:
自动排除 eBPF 采集器自身(tracepilot)、ADB 进程(adbd、shell svc)等无关线程。
核心优势: 传统的 PID-Centric 分析无法将内核事件与用户体验关联。帧对齐技术使得 TracePilot 能够回答"哪个线程、在多长时间窗口内、对哪一帧的卡顿负责",实现从内核观测到用户体验的语义映射。
+--------------------------------------------------+
| Ground Truth Layer |
| Perfetto FrameTimeline / jank / frame token |
+--------------------------+-----------------------+
|
v
+--------------------------------------------------+
| Semantic Identity Layer |
| package / UID / session / process instance / role |
+--------------------------+-----------------------+
|
v
+--------------------------------------------------+
| eBPF Evidence Layer |
| sched / wakeup / binder / futex / freq / reclaim |
+--------------------------+-----------------------+
|
v
+--------------------------------------------------+
| Critical Path Graph Builder |
| frame-window dependency graph |
| UI / Render / Binder / SurfaceFlinger / Resource |
+--------------------------+-----------------------+
|
v
+--------------------------------------------------+
| ML / Heuristic Ranking Layer |
| critical thread score / jank cause classification |
+--------------------------+-----------------------+
|
v
+--------------------------------------------------+
| Safe Hint Engine |
| whitelist / TTL / rollback / budget / audit |
+--------------------------+-----------------------+
|
v
+--------------------------------------------------+
| User-space Actuator |
| uclamp / affinity / cgroup / priority hint |
+--------------------------------------------------+
User Interaction
-> App package / UID
-> App Session / Activity / Window
-> Frame token
-> Process instance
-> PID / TID
| 场景 | 数据路径 | 说明 |
|---|---|---|
| 页面切换(QQ) | ebpf/ebpf_data/QQ页面切换场景/ | QQ 聊天界面滑动、页面跳转等操作下的调度与帧数据 |
| 页面切换(基础版) | ebpf/ebpf_data/页面切换-基础版数据/ | 基础页面切换场景的 perfetto trace 与事件记录 |
| 信息流滚动 | ebpf/ebpf_data/feed_scroll/ | Chrome 信息流滚动场景的帧统计、线程分析、Binder/ftrace 补充数据与 CriticalScore 评分 |
| 相机 | ebpf/ebpf_data/camera/ | 相机启动与预览场景的行为特征 |
| 页面切换-视频浏览 | ebpf/ebpf_data/页面切换-视频浏览数据/ | 页面切换 + 视频浏览双场景,含 Perfetto trace、eBPF 事件、CriticalPath 图、Inference 证据链、多会话对比报告 |
- eBPF 原始事件:sched_switch、Binder 事务、锁竞争等 ringbuf 输出
- Perfetto trace:用于帧边界对齐与 jank 标定
- 行为特征:经聚合与特征工程提取的 CSV 特征表
- 分析报告:场景级的行为分析、线程重要性排序、优化建议
| 报告 | 路径 |
|---|---|
| 页面切换场景数据分析报告 | behavior_analysis_report.md |
| 页面切换-基础版数据分析报告 | 页面切换-基础版数据分析报告.md |
| 信息流滚动场景数据分析报告 | feed_scroll_analysis_report.md |
| 页面切换-视频浏览综合分析报告 | 页面切换-视频浏览综合分析报告.md |
| 页面切换-视频浏览技术报告 | 页面切换-视频浏览技术报告.md |
探针源码位于 ebpf/src/
| 探针 | 采集内容 |
|---|---|
sched_switch / sched_wakeup |
线程调度事件,计算 wakeup-to-run latency、runnable delay |
binder_transaction / binder_transaction_received |
Binder 跨进程调用,分析通信延迟 |
futex wait / wake |
锁等待/唤醒,识别锁竞争阻塞 |
cpu_frequency |
CPU 频率变化,分析大小核负载 |
- Binder 依赖图:构建跨进程调用链,计算 binder_dependency_centrality
- Futex 等待图:追踪锁等待关系,量化 futex_wait_contribution
- CPU 频率归因:区分大小核运行,计算 freq_throttle_ratio
- Jank 根因分类器:基于图拓扑自动分类卡顿原因
- Thermal 深化:温控曲线提取、jank 窗口温升、throttle_score
- Inference 证据链融合:多信号加权 → hypothesis + confidence
- 多会话对比:jank 率、主因、Top-1 重叠矩阵
- Learned policy:DecisionTree 模型训练 + C 头文件导出
- 页面切换场景 eBPF 程序 — 位于
page_turning/子目录 - 页面切换-基础版 完整项目 —
ebpf/src/页面切换-基础版/,包含 eBPF 探针源码(tracepilot.bpf.c)、C 加载器、Python 分析脚本、原始采集事件及分析报告 - 页面切换-视频浏览增强版 完整项目 —
ebpf/src/页面切换-视频浏览增强版/,支持双场景分析(页面切换 + 视频浏览),含 Binder/Futex 依赖图、温控深化、Inference 证据链融合、多会话对比
Frame node → UI thread → RenderThread → Binder client/server → system_server → SurfaceFlinger → futex wait → CPU resource → memory reclaim → I/O wait
| 边类型 | 含义 |
|---|---|
| WAKEUP | 线程唤醒关系 |
| RUNNABLE_WAIT | 就绪但未分配到 CPU |
| BINDER_CALL | Binder 跨进程调用 |
| FUTEX_WAIT | 锁等待 |
| CPU_RUN | 在 CPU 上运行 |
| PREEMPTED_BY | 被抢占 |
| FRAME_DEPENDENCY | 帧依赖关系 |
| RESOURCE_STALL | 资源瓶颈 |
| DECODE_DEPENDENCY | 视频解码依赖 |
| BUFFER_QUEUE | 缓冲区队列等待 |
| THERMAL_STALL | 温控导致的停滞 |
| NETWORK_WAIT | 网络等待 |
页面切换场景 — 关键路径图:
页面切换场景 — Binder 依赖图:
视频浏览场景 — 关键路径图:
更多图例见
doc/report/目录下的分析报告。
通用公式:
CriticalScore(tid) =
a × frame_window_overlap
+ b × log1p(runnable_delay_p95)
+ c × binder_dependency_centrality
+ d × futex_wait_contribution
+ e × render_path_proximity
+ f × repeated_jank_cooccurrence
- g × background_penalty
页面切换场景权重:
CriticalScore = 0.30×overlap + 0.10×log1p(rd) + 0.25×binder
+ 0.10×futex + 0.20×render - 0.05×bg
视频浏览场景权重:
CriticalScore = 0.15×overlap + 0.10×log1p(rd) + 0.15×binder
+ 0.05×futex + 0.10×render - 0.05×bg
+ 0.20×decode + 0.10×thermal + 0.15×buffer - 0.05×net
| 层级 | 内容 | 状态 |
|---|---|---|
| Step 1:基础管线 | eBPF 采集 + Perfetto ground truth + frame window 聚合 + 角色识别 + 临时 hint | ✅ 已完成 |
| Step 2:增强 | Binder/futex 依赖图 + CPU 频率分析 + jank 分类 + 对比实验 | ✅ 已完成 |
| Step 3:前沿 | Thermal 深化 + Inference 证据链融合 + 多会话对比 + Learned policy | ✅ 已完成 |
- ✅ eBPF 探针采集 sched_switch / sched_wakeup
- ✅ Perfetto FrameTimeline 采集 jank ground truth
- ✅ 多场景数据采集(页面切换、信息流、相机)
- ✅ 行为特征提取与数据分析报告
- ✅ Binder 事务/回复依赖图追踪
- ✅ Futex 等待/唤醒图追踪
- ✅ CPU 频率追踪(大小核归因)
- ✅ Jank 根因分类器
- ✅ 启发式策略对比
- ✅ Thermal 深化(温控曲线提取、jank 窗口温升、throttle_score)
- ✅ Inference-aware 证据链融合(多信号加权 → hypothesis + confidence)
- ✅ Multi-session 多场景对比(jank 率、主因、Top-1 重叠矩阵)
- ✅ Learned policy(DecisionTree 模型训练 + C 头文件导出)
- ⏸ Cuttlefish / sched_ext(留作 future work)
| 类型 | 说明 |
|---|---|
| BOOST_THREAD | 提升线程优先级 |
| PIN_TO_BIG_CORE_SHORT | 短暂固定到大核 |
| PROTECT_UI_CHAIN | 保护 UI 依赖链 |
| LOWER_BACKGROUND_COMPETITOR | 降低后台竞争 |
| UCLAMP_MIN_TEMPORARY | 临时 uclamp 下限 |
允许: 前台 App UID、RenderThread/UI thread/确认的 Binder 依赖链、带 TTL、可回滚、记录审计日志
禁止: 直呼 PID boost、无 TTL hint、模糊/无差别调度、直接杀进程、修改 system_server 全局参数
- 实验机:Pixel 6a(解锁 + root,支持自定义 eBPF 加载)
- 主数据流:eBPF → ringbuf → 落盘 → 离线处理 → 特征工程 → 行为分析
- 辅助工具:Perfetto FrameTimeline 用于 ground truth 标定
- 分析框架:Python 数据处理 + 依赖图构建 + 关键线程评分
- eBPF 探针源码与采集配置说明
- 多场景数据集(原始事件 + 特征表 + 分析报告)
- 行为分析工具链与报告生成脚本
- 依赖关键路径图构建与评分工具
- Learned Policy 决策树模型(
learned_model.h,可嵌入 loader) - 实验报告:场景分析、特征重要性、优化建议
- 自定义 eBPF 依赖 解锁与 root,需排除运营商锁机器
- 多场景数据的标注与对齐依赖人工校验
注: 有些刚开始的阶段没有会议记录,是因为没有进行相关的记录,不是该阶段没有进行会议
| 项目阶段 | 日期 | 项目进展 | 工作安排 |
|---|---|---|---|
| 选题调研 | 3/9 ~ 3/15(第二周) | 研读往年项目 | 潘智勇:文件系统相关 贺小轩:rust改写相关 李松茂:任务调度相关 杨子皓,邵晨轩:rust改写 |
| 选题调研 | 3/16 ~ 3/22(第三周) | 开会通过自适应AI任务调度系统选题并向老师报告 | 李松茂:该方向的提出者;潘智勇:在树莓派上实现最小闭环并验证可行性并向老师汇报;贺小轩,杨子皓,邵晨轩:继续调研相关技术并完善报告 |
| 选题调研 | 3/23 ~ 3/29(第四周) | 由潘智勇向老师汇报后,答复为过于简单,很难做深。遂决定改变选题,将rust改写选题提交,被评价为过于简单。会议记录 | 贺小轩:提出rust改写方案 杨子皓:完善调研报告 潘智勇:向老师汇报 |
| 选题调研 | 3/30 ~ 4/3(第五周) | 提交六个选题,评价为四个深度不够,剩余两个可行性不高,开会决定继续调研。会议记录 | 李松茂:鸿蒙系统的LLM调优 贺小轩:鸿蒙异构内存 潘智勇:mini-VFS,fuse文件系统 杨子皓:rust改写NuttX的VFS 邵晨轩:AIOS的智能体操作系统 |
| 选题调研 | 4/3 ~ 4/5(第五周) | 潘智勇提交使用eBPF技术来优化linux调度器;邵晨轩提交面向AI agent的安全沙盒调研 老师认为潘智勇提出的使用eBPF技术方案可以,但是不要考虑linux,考虑鸿蒙或安卓,因为预调用对移动端帮助较大 | 潘智勇:调研了eBPF技术用于对linux的调度器优化 邵晨轩:调研了AIOS的相关技术和需求 |
| 选题调研 | 4/6 ~ 4/12(第六周) | 老师基本认可了在安卓系统的方案,但是数据来源有问题,虚拟环境体现不了真实用户数据,需要改为实体真机 | 李松茂,杨子皓:数据集调研 潘智勇,贺小轩:手机型号选择调研 |
| 立项 | 4/13 ~ 4/19(第七周) | 与老师对齐实验设备:pixel 6A(安卓14,root用magisk)并完成可行性报告。会议记录 | 潘智勇:购买真机并进行真机测试 邵晨轩,杨子皓:eBPF采集技术可行性报告 贺小轩:模型可行性报告 李松茂:将决策建议写入内核可行性报告 |
| 准备汇报 | 4/20 ~ 4/26(第八周) | 准备可行性汇报。会议记录 | 调研:李松茂,贺小轩 实现一个特定场景下的数据采集和处理:邵晨轩,潘智勇,杨子皓 交叉编译环境的配置:潘智勇 |
| 初步工作 | 4/27 ~ 5/1(第九周) | 完成交叉编译环境的搭建和对三个常见的场景进行eBPF信息采集和处理。页面切换场景:ebpf/src/page_turning,对应数据处理报告:behavior_analysis_report.md;信息流滚动场景数据:ebpf/ebpf_data/feed_scroll,对应数据处理报告:feed_scroll_analysis_report.md | 中期汇报:潘智勇 |
| 数据进一步采集与处理 | 5/4 ~ 5/10(第十周) | 对中期汇报得到的反馈进行调研和进一步工作,会议记录 | 调研:李松茂,贺小轩 实现观测和处理:潘智勇,邵晨轩,杨子皓 |
| 场景拓展与增强 | 5/11 ~ 5/24(第十一至十二周) | 完成页面切换、拍照、浏览器三个场景的基础部分(eBPF 采集 + Perfetto 配置 + 分析工具 + 多 App 测试);推进支付、游戏、视频三个拓展场景的基础部分;并行进行页面切换、拍照、浏览器的增强部分(深度帧分析、系统开销归因、评分模型优化) | 潘智勇,邵晨轩,杨子皓 |
| 页面切换-视频浏览增强版 | 5/25 ~ 6/8(第十三至十四周) | 完成 eBPF + Perfetto 的交互关键路径图(ICPG)双场景分析系统:Binder/Futex 依赖图、CPU 频率归因、Jank 分类器、Thermal 深化、Inference 证据链融合、多会话对比、Learned Policy 决策树模型;在 Pixel 6a 上完成页面切换与视频浏览两个场景的采集与分析,输出技术报告与综合分析报告 | 潘智勇 |