feat: 将 profile.sh 重写为场景化版本,支持按交互场景录制 Perfetto trace
- 引入 --scenario 参数,支持 15 种预设交互场景 - 自动场景通过 adb 自动执行操作(滑动翻页、拖拽折叠、切换视图等) - 手动场景提供操作指引并保留倒计时准备 - 批量录制模式(--all)自动遍历所有场景并生成汇总报告 - 输出文件按场景名命名,支持场景级对比分析
This commit is contained in:
parent
829f89eb7c
commit
d933ca3e41
@ -1,59 +1,549 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
#
|
#
|
||||||
# YaYa 性能追踪脚本
|
# YaYa 性能追踪脚本(场景化版)
|
||||||
# 使用 Perfetto 抓取应用 trace,保存到 logs/ 目录
|
# 支持按交互场景录制 Perfetto trace,精准定位各场景性能
|
||||||
#
|
#
|
||||||
# 用法:
|
# 用法:
|
||||||
# ./scripts/profile.sh # 默认抓取 8 秒
|
# ./scripts/profile.sh # 默认抓取 8 秒(向后兼容)
|
||||||
# ./scripts/profile.sh 15 # 抓取 15 秒
|
# ./scripts/profile.sh --scenario month_browse --trace 15
|
||||||
# ./scripts/profile.sh --no-launch # 不自动启动应用(应用已在运行)
|
# ./scripts/profile.sh --list-scenarios # 列出所有场景
|
||||||
# ./scripts/profile.sh --trace # 使用 trace 构建类型(保留自定义 trace 标记)
|
# ./scripts/profile.sh --help # 帮助
|
||||||
#
|
#
|
||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
PACKAGE="plus.rua.project"
|
PACKAGE="plus.rua.project"
|
||||||
ACTIVITY="plus.rua.project.MainActivity"
|
MAIN_ACTIVITY="plus.rua.project.MainActivity"
|
||||||
|
TOOLS_ACTIVITY="plus.rua.project.ToolsActivity"
|
||||||
|
DATECHECKER_ACTIVITY="plus.rua.project.DateCheckerActivity"
|
||||||
|
ABOUT_ACTIVITY="plus.rua.project.AboutActivity"
|
||||||
|
LICENSES_ACTIVITY="plus.rua.project.LicensesActivity"
|
||||||
|
|
||||||
PROJECT_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
PROJECT_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
||||||
LOGS_DIR="${PROJECT_ROOT}/logs"
|
LOGS_DIR="${PROJECT_ROOT}/logs"
|
||||||
|
|
||||||
# 解析参数
|
# 默认参数
|
||||||
DURATION_SEC=8
|
DURATION_SEC=8
|
||||||
NO_LAUNCH=false
|
NO_LAUNCH=false
|
||||||
USE_TRACE_BUILD=false
|
USE_TRACE_BUILD=false
|
||||||
|
SCENARIO=""
|
||||||
|
SCENARIO_NAME=""
|
||||||
|
SCENARIO_DESC=""
|
||||||
|
BG_PID=""
|
||||||
|
RUN_ALL=false
|
||||||
|
|
||||||
for arg in "$@"; do
|
# ──────────────────────────────────────────
|
||||||
case "$arg" in
|
# 场景列表
|
||||||
|
# ──────────────────────────────────────────
|
||||||
|
list_scenarios() {
|
||||||
|
cat <<'EOF'
|
||||||
|
可用场景:
|
||||||
|
|
||||||
|
主日历场景:
|
||||||
|
month_browse - 月视图左右滑动翻页(自动滑动)
|
||||||
|
date_select - 点击不同日期(需手动:依次点击多个日期)
|
||||||
|
collapse_expand - 折叠/展开 月视图↔周视图(自动拖拽)
|
||||||
|
year_view - 年视图切换+年份滑动(自动)
|
||||||
|
year_select - 年视图中选择月份返回(自动)
|
||||||
|
today_jump - 跳转到今天(自动)
|
||||||
|
menu_toggle - FAB 菜单打开关闭(自动)
|
||||||
|
legal_holiday - 显示调休切换(自动)
|
||||||
|
cross_month - 跨月日期选择(需手动:点击灰色日期)
|
||||||
|
|
||||||
|
其他页面:
|
||||||
|
tools - 工具页面(自动打开)
|
||||||
|
date_checker - 日期检查器(需手动:添加行、输入天数、滑动删除)
|
||||||
|
about - 关于页面(自动打开)
|
||||||
|
licenses - 开源许可列表(自动打开+滑动)
|
||||||
|
|
||||||
|
综合场景:
|
||||||
|
full_flow - 完整用户流程(需手动:按提示操作所有功能)
|
||||||
|
all_activities - 遍历所有 Activity(自动)
|
||||||
|
|
||||||
|
批量录制:
|
||||||
|
--all - 自动依次录制所有自动场景,最后生成汇总报告
|
||||||
|
|
||||||
|
默认场景(向后兼容):
|
||||||
|
(不指定 --scenario)启动应用,抓取指定时长
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
# ──────────────────────────────────────────
|
||||||
|
# 参数解析
|
||||||
|
# ──────────────────────────────────────────
|
||||||
|
while [ $# -gt 0 ]; do
|
||||||
|
case "$1" in
|
||||||
--no-launch)
|
--no-launch)
|
||||||
NO_LAUNCH=true
|
NO_LAUNCH=true
|
||||||
|
shift
|
||||||
;;
|
;;
|
||||||
--trace)
|
--trace)
|
||||||
USE_TRACE_BUILD=true
|
USE_TRACE_BUILD=true
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--scenario)
|
||||||
|
if [ $# -lt 2 ]; then
|
||||||
|
echo "错误: --scenario 需要指定场景名"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
SCENARIO="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--all)
|
||||||
|
RUN_ALL=true
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--list-scenarios)
|
||||||
|
list_scenarios
|
||||||
|
exit 0
|
||||||
;;
|
;;
|
||||||
--help|-h)
|
--help|-h)
|
||||||
echo "用法: $0 [秒数] [--no-launch] [--trace]"
|
cat <<EOF
|
||||||
echo ""
|
用法: $0 [秒数] [--no-launch] [--trace] [--scenario <场景>] [--all]
|
||||||
echo "选项:"
|
|
||||||
echo " 秒数 抓取时长(默认 8 秒)"
|
选项:
|
||||||
echo " --no-launch 不自动启动应用"
|
秒数 抓取时长(默认 8 秒,--all 时每个场景默认 10 秒)
|
||||||
echo " --trace 使用 trace 构建(release 优化 + 保留 trace 标记)"
|
--no-launch 不自动启动应用
|
||||||
echo " --help 显示此帮助"
|
--trace 使用 trace 构建(release + trace 标记保留)
|
||||||
|
--scenario <场景> 指定交互场景,脚本会引导或自动执行对应操作
|
||||||
|
--all 批量录制所有自动场景,生成汇总报告
|
||||||
|
--list-scenarios 列出所有可用场景
|
||||||
|
--help 显示此帮助
|
||||||
|
|
||||||
|
示例:
|
||||||
|
# 录制月视图滑动翻页 15 秒
|
||||||
|
$0 --scenario month_browse --trace 15
|
||||||
|
|
||||||
|
# 录制完整用户流程 30 秒(需手动按提示操作)
|
||||||
|
$0 --scenario full_flow --trace 30
|
||||||
|
|
||||||
|
# 录制日期检查器操作(需手动)
|
||||||
|
$0 --scenario date_checker --trace 20
|
||||||
|
|
||||||
|
# 批量录制所有自动场景(每个 10 秒)
|
||||||
|
$0 --all --trace 10
|
||||||
|
|
||||||
|
# 默认录制(向后兼容)
|
||||||
|
$0 --trace 15
|
||||||
|
EOF
|
||||||
exit 0
|
exit 0
|
||||||
;;
|
;;
|
||||||
[0-9]*)
|
[0-9]*)
|
||||||
DURATION_SEC="$arg"
|
DURATION_SEC="$1"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "未知参数: $1"
|
||||||
|
echo "使用 --help 查看帮助"
|
||||||
|
exit 1
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
|
# ──────────────────────────────────────────
|
||||||
|
# 工具函数
|
||||||
|
# ──────────────────────────────────────────
|
||||||
|
|
||||||
|
# 获取屏幕尺寸
|
||||||
|
get_screen_size() {
|
||||||
|
adb shell wm size 2>/dev/null | awk '{print $3}'
|
||||||
|
}
|
||||||
|
|
||||||
|
# 获取屏幕中心坐标
|
||||||
|
get_screen_center() {
|
||||||
|
local size w h
|
||||||
|
size=$(get_screen_size)
|
||||||
|
w=$(echo "$size" | cut -dx -f1)
|
||||||
|
h=$(echo "$size" | cut -dx -f2)
|
||||||
|
echo "$w $h"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 清理后台进程
|
||||||
|
cleanup_bg() {
|
||||||
|
if [ -n "$BG_PID" ] && kill -0 "$BG_PID" 2>/dev/null; then
|
||||||
|
kill "$BG_PID" 2>/dev/null || true
|
||||||
|
wait "$BG_PID" 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
trap cleanup_bg EXIT
|
||||||
|
|
||||||
|
# 等待 trace 开始后再执行操作
|
||||||
|
wait_then_do() {
|
||||||
|
local delay_sec="$1"
|
||||||
|
shift
|
||||||
|
(
|
||||||
|
sleep "$delay_sec"
|
||||||
|
"$@"
|
||||||
|
) &
|
||||||
|
BG_PID=$!
|
||||||
|
}
|
||||||
|
|
||||||
|
# ──────────────────────────────────────────
|
||||||
|
# 场景执行
|
||||||
|
# ──────────────────────────────────────────
|
||||||
|
run_scenario() {
|
||||||
|
local scenario="$1"
|
||||||
|
local screen_size screen_w screen_h cx cy
|
||||||
|
screen_size=$(get_screen_size)
|
||||||
|
if [ -z "$screen_size" ]; then
|
||||||
|
echo "错误: 无法获取屏幕尺寸"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
screen_w=$(echo "$screen_size" | cut -dx -f1)
|
||||||
|
screen_h=$(echo "$screen_size" | cut -dx -f2)
|
||||||
|
cx=$((screen_w / 2))
|
||||||
|
cy=$((screen_h / 2))
|
||||||
|
# 日历网格大致区域(屏幕中间偏上)
|
||||||
|
local grid_y=$((screen_h * 35 / 100))
|
||||||
|
# FAB 按钮大致位置(右下)
|
||||||
|
local fab_x=$((screen_w * 85 / 100))
|
||||||
|
local fab_y=$((screen_h * 85 / 100))
|
||||||
|
# BottomCard 拖拽区域(屏幕下半部分)
|
||||||
|
local bottom_y=$((screen_h * 70 / 100))
|
||||||
|
|
||||||
|
case "$scenario" in
|
||||||
|
month_browse)
|
||||||
|
SCENARIO_NAME="月视图滑动翻页"
|
||||||
|
SCENARIO_DESC="在月视图中快速左右滑动翻页,测试 CalendarPager 重组和绘制性能"
|
||||||
|
echo ""
|
||||||
|
echo "[场景] ${SCENARIO_NAME}"
|
||||||
|
echo " ${SCENARIO_DESC}"
|
||||||
|
echo ""
|
||||||
|
adb shell am start -n "${PACKAGE}/${MAIN_ACTIVITY}" >/dev/null 2>&1
|
||||||
|
sleep 1
|
||||||
|
echo " → 自动执行:trace 开始后将连续左右滑动翻页"
|
||||||
|
wait_then_do 2 bash -c "
|
||||||
|
for i in 1 2 3 4 5 6 7 8; do
|
||||||
|
adb shell input swipe $((screen_w*80/100)) $grid_y $((screen_w*20/100)) $grid_y 200
|
||||||
|
sleep 0.4
|
||||||
|
adb shell input swipe $((screen_w*20/100)) $grid_y $((screen_w*80/100)) $grid_y 200
|
||||||
|
sleep 0.4
|
||||||
|
done
|
||||||
|
"
|
||||||
|
;;
|
||||||
|
|
||||||
|
date_select)
|
||||||
|
SCENARIO_NAME="点击日期选择"
|
||||||
|
SCENARIO_DESC="依次点击不同日期,测试 DayCell 重组和 AnimatedGif 动画性能"
|
||||||
|
echo ""
|
||||||
|
echo "[场景] ${SCENARIO_NAME}"
|
||||||
|
echo " ${SCENARIO_DESC}"
|
||||||
|
echo ""
|
||||||
|
adb shell am start -n "${PACKAGE}/${MAIN_ACTIVITY}" >/dev/null 2>&1
|
||||||
|
sleep 1
|
||||||
|
echo " → 请手动操作:trace 开始后,依次点击日历中不同的日期(建议点击 5-10 个)"
|
||||||
|
echo " 可尝试点击同一行不同列、跨行点击,观察选中动画"
|
||||||
|
;;
|
||||||
|
|
||||||
|
collapse_expand)
|
||||||
|
SCENARIO_NAME="折叠/展开 月视图↔周视图"
|
||||||
|
SCENARIO_DESC="拖拽 BottomCard 上下切换月视图和周视图,测试折叠动画和布局变化性能"
|
||||||
|
echo ""
|
||||||
|
echo "[场景] ${SCENARIO_NAME}"
|
||||||
|
echo " ${SCENARIO_DESC}"
|
||||||
|
echo ""
|
||||||
|
adb shell am start -n "${PACKAGE}/${MAIN_ACTIVITY}" >/dev/null 2>&1
|
||||||
|
sleep 1
|
||||||
|
echo " → 自动执行:trace 开始后将自动拖拽 BottomCard 上下切换"
|
||||||
|
wait_then_do 2 bash -c "
|
||||||
|
for i in 1 2 3 4 5; do
|
||||||
|
# 向上拖拽(月→周)
|
||||||
|
adb shell input swipe $cx $bottom_y $cx $((screen_h*40/100)) 400
|
||||||
|
sleep 0.8
|
||||||
|
# 向下拖拽(周→月)
|
||||||
|
adb shell input swipe $cx $((screen_h*40/100)) $cx $bottom_y 400
|
||||||
|
sleep 0.8
|
||||||
|
done
|
||||||
|
"
|
||||||
|
;;
|
||||||
|
|
||||||
|
year_view)
|
||||||
|
SCENARIO_NAME="年视图切换+年份滑动"
|
||||||
|
SCENARIO_DESC="打开年视图后在年份间左右滑动,测试 YearGridView 重组和 AnimatedContent 转场性能"
|
||||||
|
echo ""
|
||||||
|
echo "[场景] ${SCENARIO_NAME}"
|
||||||
|
echo " ${SCENARIO_DESC}"
|
||||||
|
echo ""
|
||||||
|
adb shell am start -n "${PACKAGE}/${MAIN_ACTIVITY}" >/dev/null 2>&1
|
||||||
|
sleep 1
|
||||||
|
# 打开年视图(点击 FAB → 年视图)
|
||||||
|
adb shell input tap "$fab_x" "$fab_y"
|
||||||
|
sleep 0.5
|
||||||
|
# 点击"年视图"菜单项(在 FAB 上方约 100px)
|
||||||
|
adb shell input tap "$fab_x" $((fab_y - 120))
|
||||||
|
sleep 0.8
|
||||||
|
echo " → 自动执行:已打开年视图,trace 开始后将滑动浏览年份"
|
||||||
|
wait_then_do 2 bash -c "
|
||||||
|
for i in 1 2 3 4; do
|
||||||
|
adb shell input swipe $((screen_w*80/100)) $cy $((screen_w*20/100)) $cy 200
|
||||||
|
sleep 0.5
|
||||||
|
adb shell input swipe $((screen_w*20/100)) $cy $((screen_w*80/100)) $cy 200
|
||||||
|
sleep 0.5
|
||||||
|
done
|
||||||
|
"
|
||||||
|
;;
|
||||||
|
|
||||||
|
year_select)
|
||||||
|
SCENARIO_NAME="年视图中选择月份"
|
||||||
|
SCENARIO_DESC="在年视图中点击不同月份返回月视图,测试 MonthView→YearView→MonthView 完整转场链"
|
||||||
|
echo ""
|
||||||
|
echo "[场景] ${SCENARIO_NAME}"
|
||||||
|
echo " ${SCENARIO_DESC}"
|
||||||
|
echo ""
|
||||||
|
adb shell am start -n "${PACKAGE}/${MAIN_ACTIVITY}" >/dev/null 2>&1
|
||||||
|
sleep 1
|
||||||
|
# 打开年视图
|
||||||
|
adb shell input tap "$fab_x" "$fab_y"
|
||||||
|
sleep 0.5
|
||||||
|
adb shell input tap "$fab_x" $((fab_y - 120))
|
||||||
|
sleep 0.8
|
||||||
|
echo " → 自动执行:trace 开始后将依次点击不同的迷你月份"
|
||||||
|
wait_then_do 2 bash -c "
|
||||||
|
# 点击第1行不同月份(大致坐标)
|
||||||
|
adb shell input tap $((screen_w*20/100)) $((screen_h*25/100))
|
||||||
|
sleep 1.0
|
||||||
|
# 重新打开年视图
|
||||||
|
adb shell input tap $fab_x $fab_y
|
||||||
|
sleep 0.3
|
||||||
|
adb shell input tap $fab_x $((fab_y - 120))
|
||||||
|
sleep 0.5
|
||||||
|
adb shell input tap $((screen_w*50/100)) $((screen_h*25/100))
|
||||||
|
sleep 1.0
|
||||||
|
# 再试一个
|
||||||
|
adb shell input tap $fab_x $fab_y
|
||||||
|
sleep 0.3
|
||||||
|
adb shell input tap $fab_x $((fab_y - 120))
|
||||||
|
sleep 0.5
|
||||||
|
adb shell input tap $((screen_w*80/100)) $((screen_h*50/100))
|
||||||
|
sleep 1.0
|
||||||
|
"
|
||||||
|
;;
|
||||||
|
|
||||||
|
today_jump)
|
||||||
|
SCENARIO_NAME="跳转到今天"
|
||||||
|
SCENARIO_DESC="先翻到非当月,然后点击"今天"按钮跳转,测试自动翻页和选中动画"
|
||||||
|
echo ""
|
||||||
|
echo "[场景] ${SCENARIO_NAME}"
|
||||||
|
echo " ${SCENARIO_DESC}"
|
||||||
|
echo ""
|
||||||
|
adb shell am start -n "${PACKAGE}/${MAIN_ACTIVITY}" >/dev/null 2>&1
|
||||||
|
sleep 1
|
||||||
|
# 先翻几页离开当月
|
||||||
|
adb shell input swipe $((screen_w*20/100)) $grid_y $((screen_w*80/100)) $grid_y 200
|
||||||
|
sleep 0.5
|
||||||
|
adb shell input swipe $((screen_w*20/100)) $grid_y $((screen_w*80/100)) $grid_y 200
|
||||||
|
sleep 0.5
|
||||||
|
echo " → 自动执行:trace 开始后将点击"今天"按钮"
|
||||||
|
# "今天"按钮大致在左上角
|
||||||
|
wait_then_do 2 bash -c "
|
||||||
|
adb shell input tap $((screen_w*15/100)) $((screen_h*12/100))
|
||||||
|
sleep 2.0
|
||||||
|
adb shell input swipe $((screen_w*20/100)) $grid_y $((screen_w*80/100)) $grid_y 200
|
||||||
|
sleep 0.5
|
||||||
|
adb shell input tap $((screen_w*15/100)) $((screen_h*12/100))
|
||||||
|
"
|
||||||
|
;;
|
||||||
|
|
||||||
|
menu_toggle)
|
||||||
|
SCENARIO_NAME="FAB 菜单打开关闭"
|
||||||
|
SCENARIO_DESC="反复打开/关闭 FAB 菜单,测试 AnimatedVisibility 缩放动画性能"
|
||||||
|
echo ""
|
||||||
|
echo "[场景] ${SCENARIO_NAME}"
|
||||||
|
echo " ${SCENARIO_DESC}"
|
||||||
|
echo ""
|
||||||
|
adb shell am start -n "${PACKAGE}/${MAIN_ACTIVITY}" >/dev/null 2>&1
|
||||||
|
sleep 1
|
||||||
|
echo " → 自动执行:trace 开始后将反复点击 FAB"
|
||||||
|
wait_then_do 2 bash -c "
|
||||||
|
for i in 1 2 3 4 5 6 7 8 9 10; do
|
||||||
|
adb shell input tap $fab_x $fab_y
|
||||||
|
sleep 0.5
|
||||||
|
done
|
||||||
|
"
|
||||||
|
;;
|
||||||
|
|
||||||
|
legal_holiday)
|
||||||
|
SCENARIO_NAME="显示调休切换"
|
||||||
|
SCENARIO_DESC="切换"显示调休"开关,测试 DayCell 大规模重组和 staggered 动画性能"
|
||||||
|
echo ""
|
||||||
|
echo "[场景] ${SCENARIO_NAME}"
|
||||||
|
echo " ${SCENARIO_DESC}"
|
||||||
|
echo ""
|
||||||
|
adb shell am start -n "${PACKAGE}/${MAIN_ACTIVITY}" >/dev/null 2>&1
|
||||||
|
sleep 1
|
||||||
|
echo " → 自动执行:trace 开始后将反复切换"显示调休""
|
||||||
|
wait_then_do 2 bash -c "
|
||||||
|
for i in 1 2 3 4; do
|
||||||
|
# 打开菜单
|
||||||
|
adb shell input tap $fab_x $fab_y
|
||||||
|
sleep 0.4
|
||||||
|
# 点击"显示调休"(在 FAB 上方约 200px)
|
||||||
|
adb shell input tap $fab_x $((fab_y - 200))
|
||||||
|
sleep 1.0
|
||||||
|
done
|
||||||
|
"
|
||||||
|
;;
|
||||||
|
|
||||||
|
cross_month)
|
||||||
|
SCENARIO_NAME="跨月日期选择"
|
||||||
|
SCENARIO_DESC="点击上月或下月的灰色日期,测试跨月自动跳转和 pager 同步性能"
|
||||||
|
echo ""
|
||||||
|
echo "[场景] ${SCENARIO_NAME}"
|
||||||
|
echo " ${SCENARIO_DESC}"
|
||||||
|
echo ""
|
||||||
|
adb shell am start -n "${PACKAGE}/${MAIN_ACTIVITY}" >/dev/null 2>&1
|
||||||
|
sleep 1
|
||||||
|
echo " → 请手动操作:trace 开始后,点击日历中灰色显示的上月/下月日期"
|
||||||
|
echo " 建议:先点击右侧灰色日期(下月),再点击左侧灰色日期(上月)"
|
||||||
|
;;
|
||||||
|
|
||||||
|
tools)
|
||||||
|
SCENARIO_NAME="工具页面"
|
||||||
|
SCENARIO_DESC="打开工具页面,测试 Activity 转场动画和 ToolsScreen 渲染性能"
|
||||||
|
echo ""
|
||||||
|
echo "[场景] ${SCENARIO_NAME}"
|
||||||
|
echo " ${SCENARIO_DESC}"
|
||||||
|
echo ""
|
||||||
|
adb shell am start -n "${PACKAGE}/${TOOLS_ACTIVITY}" >/dev/null 2>&1
|
||||||
|
sleep 1
|
||||||
|
echo " → 自动执行:工具页面已打开,trace 期间保持静态"
|
||||||
|
;;
|
||||||
|
|
||||||
|
date_checker)
|
||||||
|
SCENARIO_NAME="日期检查器"
|
||||||
|
SCENARIO_DESC="在日期检查器中进行添加行、输入天数、滑动删除等操作,测试复杂表单性能"
|
||||||
|
echo ""
|
||||||
|
echo "[场景] ${SCENARIO_NAME}"
|
||||||
|
echo " ${SCENARIO_DESC}"
|
||||||
|
echo ""
|
||||||
|
adb shell am start -n "${PACKAGE}/${DATECHECKER_ACTIVITY}" >/dev/null 2>&1
|
||||||
|
sleep 1
|
||||||
|
echo " → 请手动操作:trace 开始后,执行以下操作"
|
||||||
|
echo " 1. 点击 FAB (+) 添加一行"
|
||||||
|
echo " 2. 在新行的"天数"输入框中输入数字(如 90)"
|
||||||
|
echo " 3. 点击另一行的日历图标修改到期日期"
|
||||||
|
echo " 4. 向左滑动某一行删除"
|
||||||
|
echo " 5. 修改生产日期"
|
||||||
|
;;
|
||||||
|
|
||||||
|
about)
|
||||||
|
SCENARIO_NAME="关于页面"
|
||||||
|
SCENARIO_DESC="打开关于页面,测试 Activity 转场和 AboutScreen 渲染性能"
|
||||||
|
echo ""
|
||||||
|
echo "[场景] ${SCENARIO_NAME}"
|
||||||
|
echo " ${SCENARIO_DESC}"
|
||||||
|
echo ""
|
||||||
|
adb shell am start -n "${PACKAGE}/${ABOUT_ACTIVITY}" >/dev/null 2>&1
|
||||||
|
sleep 1
|
||||||
|
echo " → 自动执行:关于页面已打开,trace 期间保持静态"
|
||||||
|
;;
|
||||||
|
|
||||||
|
licenses)
|
||||||
|
SCENARIO_NAME="开源许可列表"
|
||||||
|
SCENARIO_DESC="打开开源许可页面并上下滑动,测试 LicensesScreen 列表滑动性能"
|
||||||
|
echo ""
|
||||||
|
echo "[场景] ${SCENARIO_NAME}"
|
||||||
|
echo " ${SCENARIO_DESC}"
|
||||||
|
echo ""
|
||||||
|
adb shell am start -n "${PACKAGE}/${LICENSES_ACTIVITY}" >/dev/null 2>&1
|
||||||
|
sleep 1
|
||||||
|
echo " → 自动执行:许可页面已打开,trace 开始后将上下滑动"
|
||||||
|
wait_then_do 2 bash -c "
|
||||||
|
for i in 1 2 3 4 5; do
|
||||||
|
adb shell input swipe $cx $((screen_h*70/100)) $cx $((screen_h*30/100)) 300
|
||||||
|
sleep 0.5
|
||||||
|
adb shell input swipe $cx $((screen_h*30/100)) $cx $((screen_h*70/100)) 300
|
||||||
|
sleep 0.5
|
||||||
|
done
|
||||||
|
"
|
||||||
|
;;
|
||||||
|
|
||||||
|
full_flow)
|
||||||
|
SCENARIO_NAME="完整用户流程"
|
||||||
|
SCENARIO_DESC="覆盖所有主要交互的完整流程,综合评估整体性能"
|
||||||
|
echo ""
|
||||||
|
echo "[场景] ${SCENARIO_NAME}"
|
||||||
|
echo " ${SCENARIO_DESC}"
|
||||||
|
echo ""
|
||||||
|
adb shell am start -n "${PACKAGE}/${MAIN_ACTIVITY}" >/dev/null 2>&1
|
||||||
|
sleep 1
|
||||||
|
echo " → 请严格按以下顺序手动操作:"
|
||||||
|
echo ""
|
||||||
|
echo " 1. 左右滑动翻页 2-3 次"
|
||||||
|
echo " 2. 点击几个不同日期"
|
||||||
|
echo " 3. 向上拖拽 BottomCard 切换到周视图"
|
||||||
|
echo " 4. 在周视图中左右滑动翻周"
|
||||||
|
echo " 5. 向下拖拽展开回月视图"
|
||||||
|
echo " 6. 点击 FAB 打开菜单 → 年视图"
|
||||||
|
echo " 7. 年视图中滑动浏览年份"
|
||||||
|
echo " 8. 点击一个月份返回"
|
||||||
|
echo " 9. 点击 FAB → 显示调休(切换一次)"
|
||||||
|
echo " 10. 点击"今天"按钮"
|
||||||
|
echo " 11. 点击 FAB → 工具"
|
||||||
|
echo " 12. 在工具页点击"日期检查器""
|
||||||
|
echo " 13. 添加一行、输入天数、滑动删除一行"
|
||||||
|
echo " 14. 返回 → 返回 → 关于"
|
||||||
|
echo " 15. 点击"开放源代码许可""
|
||||||
|
echo " 16. 滑动许可列表"
|
||||||
|
echo " 17. 返回 → 返回回到主页面"
|
||||||
|
echo ""
|
||||||
|
echo " 建议在 trace 期间尽可能流畅地完成上述操作"
|
||||||
|
;;
|
||||||
|
|
||||||
|
all_activities)
|
||||||
|
SCENARIO_NAME="遍历所有 Activity"
|
||||||
|
SCENARIO_DESC="自动依次打开所有 Activity,测试 Activity 启动和转场动画性能"
|
||||||
|
echo ""
|
||||||
|
echo "[场景] ${SCENARIO_NAME}"
|
||||||
|
echo " ${SCENARIO_DESC}"
|
||||||
|
echo ""
|
||||||
|
echo " → 自动执行:trace 开始后将依次打开所有页面"
|
||||||
|
wait_then_do 2 bash -c "
|
||||||
|
sleep 1
|
||||||
|
adb shell am start -n ${PACKAGE}/${MAIN_ACTIVITY}
|
||||||
|
sleep 1.5
|
||||||
|
adb shell am start -n ${PACKAGE}/${TOOLS_ACTIVITY}
|
||||||
|
sleep 1.5
|
||||||
|
adb shell am start -n ${PACKAGE}/${ABOUT_ACTIVITY}
|
||||||
|
sleep 1.5
|
||||||
|
adb shell am start -n ${PACKAGE}/${LICENSES_ACTIVITY}
|
||||||
|
sleep 1.5
|
||||||
|
adb shell am start -n ${PACKAGE}/${DATECHECKER_ACTIVITY}
|
||||||
|
sleep 1.5
|
||||||
|
adb shell am start -n ${PACKAGE}/${MAIN_ACTIVITY}
|
||||||
|
sleep 1.0
|
||||||
|
"
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
echo "错误: 未知场景: $scenario"
|
||||||
|
echo "使用 --list-scenarios 查看可用场景"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# ──────────────────────────────────────────
|
||||||
|
# 主流程
|
||||||
|
# ──────────────────────────────────────────
|
||||||
|
|
||||||
DURATION_MS=$((DURATION_SEC * 1000))
|
DURATION_MS=$((DURATION_SEC * 1000))
|
||||||
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
|
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
|
||||||
|
|
||||||
|
# 场景后缀
|
||||||
|
SCENARIO_SUFFIX=""
|
||||||
|
if [ -n "$SCENARIO" ]; then
|
||||||
|
SCENARIO_SUFFIX="_${SCENARIO}"
|
||||||
|
fi
|
||||||
|
|
||||||
echo "========================================"
|
echo "========================================"
|
||||||
echo " YaYa 性能追踪"
|
echo " YaYa 性能追踪"
|
||||||
echo " 包名: ${PACKAGE}"
|
echo " 包名: ${PACKAGE}"
|
||||||
echo " 时长: ${DURATION_SEC}s"
|
echo " 时长: ${DURATION_SEC}s"
|
||||||
echo " 构建: $([ "$USE_TRACE_BUILD" = true ] && echo "trace (release + trace)" || echo "debug")"
|
echo " 构建: $([ "$USE_TRACE_BUILD" = true ] && echo "trace (release + trace)" || echo "debug")"
|
||||||
|
if [ -n "$SCENARIO" ]; then
|
||||||
|
echo " 场景: ${SCENARIO}"
|
||||||
|
fi
|
||||||
echo " 输出: ${LOGS_DIR}/"
|
echo " 输出: ${LOGS_DIR}/"
|
||||||
echo "========================================"
|
echo "========================================"
|
||||||
|
|
||||||
@ -85,26 +575,194 @@ if ! adb shell pm list packages | grep -q "${PACKAGE}"; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# 启动应用(如果未禁用)
|
# ──────────────────────────────────────────
|
||||||
|
# 批量录制所有自动场景
|
||||||
|
# ──────────────────────────────────────────
|
||||||
|
run_all_scenarios() {
|
||||||
|
local script="$0"
|
||||||
|
local per_scene_duration="${DURATION_SEC}"
|
||||||
|
# --all 模式下默认每个场景 10 秒
|
||||||
|
if [ "$per_scene_duration" -eq 8 ]; then
|
||||||
|
per_scene_duration=10
|
||||||
|
fi
|
||||||
|
|
||||||
|
local auto_scenarios=(
|
||||||
|
month_browse
|
||||||
|
collapse_expand
|
||||||
|
year_view
|
||||||
|
year_select
|
||||||
|
today_jump
|
||||||
|
menu_toggle
|
||||||
|
legal_holiday
|
||||||
|
tools
|
||||||
|
about
|
||||||
|
licenses
|
||||||
|
all_activities
|
||||||
|
)
|
||||||
|
local total=${#auto_scenarios[@]}
|
||||||
|
local build_flag=""
|
||||||
|
[ "$USE_TRACE_BUILD" = true ] && build_flag="--trace"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "========================================"
|
||||||
|
echo " 批量录制模式"
|
||||||
|
echo " 共 ${total} 个自动场景"
|
||||||
|
echo " 每个场景 ${per_scene_duration} 秒"
|
||||||
|
echo "========================================"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
local i=0
|
||||||
|
for s in "${auto_scenarios[@]}"; do
|
||||||
|
i=$((i + 1))
|
||||||
|
echo ""
|
||||||
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||||
|
echo " [${i}/${total}] 录制场景: ${s}"
|
||||||
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||||
|
"$script" --scenario "$s" $build_flag "$per_scene_duration"
|
||||||
|
if [ "$i" -lt "$total" ]; then
|
||||||
|
echo ""
|
||||||
|
echo " 休息 2 秒,准备下一个场景..."
|
||||||
|
sleep 2
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# 生成汇总报告
|
||||||
|
generate_summary_report "$total" "$per_scene_duration"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 生成批量录制汇总报告
|
||||||
|
generate_summary_report() {
|
||||||
|
local total="$1"
|
||||||
|
local duration="$2"
|
||||||
|
local summary_time
|
||||||
|
summary_time=$(date +%Y%m%d_%H%M%S)
|
||||||
|
local summary_file="${LOGS_DIR}/report_${summary_time}_ALL_SUMMARY.md"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "========================================"
|
||||||
|
echo " 生成批量录制汇总报告"
|
||||||
|
echo "========================================"
|
||||||
|
|
||||||
|
cat > "$summary_file" <<EOF
|
||||||
|
# YaYa 批量性能追踪汇总报告
|
||||||
|
|
||||||
|
**时间:** $(date '+%Y-%m-%d %H:%M:%S')
|
||||||
|
**设备:** ${DEVICE_MODEL} (Android ${ANDROID_VERSION})
|
||||||
|
**应用版本:** ${APP_VERSION}
|
||||||
|
**构建类型:** $([ "$USE_TRACE_BUILD" = true ] && echo "trace" || echo "debug")
|
||||||
|
**场景数:** ${total}
|
||||||
|
**每场景时长:** ${duration}s
|
||||||
|
|
||||||
|
## 各场景帧率对比
|
||||||
|
|
||||||
|
| 场景 | 总帧数 | 掉帧数 | 掉帧比例 | P50 | P90 | P99 | Slow Draw | Total PSS |
|
||||||
|
|------|--------|--------|---------|-----|-----|-----|-----------|-----------|
|
||||||
|
EOF
|
||||||
|
|
||||||
|
for s in month_browse collapse_expand year_view year_select today_jump menu_toggle legal_holiday tools about licenses all_activities; do
|
||||||
|
local report
|
||||||
|
report=$(ls -t "${LOGS_DIR}"/report_*"_${s}".md 2>/dev/null | head -1)
|
||||||
|
if [ -n "$report" ]; then
|
||||||
|
local tf jf jp p50 p90 p99 sd tp
|
||||||
|
tf=$(awk '/Total frames rendered:/{print $4; exit}' "${report}")
|
||||||
|
jf=$(awk '/掉帧数/{getline; print $2; exit}' "${report}")
|
||||||
|
jp=$(awk '/掉帧比例/{getline; print $2; exit}' "${report}")
|
||||||
|
p50=$(awk '/50th percentile/{getline; print $2; exit}' "${report}")
|
||||||
|
p90=$(awk '/90th percentile/{getline; print $2; exit}' "${report}")
|
||||||
|
p99=$(awk '/99th percentile/{getline; print $2; exit}' "${report}")
|
||||||
|
sd=$(awk '/Slow draw commands/{getline; print $2; exit}' "${report}")
|
||||||
|
tp=$(awk '/Total PSS/{getline; print $2; exit}' "${report}")
|
||||||
|
printf "| %s | %s | %s | %s | %s | %s | %s | %s | %s |\n" "$s" "${tf:-N/A}" "${jf:-N/A}" "${jp:-N/A}" "${p50:-N/A}" "${p90:-N/A}" "${p99:-N/A}" "${sd:-N/A}" "${tp:-N/A}" >> "$summary_file"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
cat >> "$summary_file" <<EOF
|
||||||
|
|
||||||
|
## 分析建议
|
||||||
|
|
||||||
|
1. **掉帧比例最高**的场景是性能瓶颈所在,优先优化
|
||||||
|
2. **Slow draw commands** 高的场景说明 GPU 绘制是瓶颈
|
||||||
|
3. **P99 延迟高**的场景说明存在偶发性卡顿
|
||||||
|
4. 对比各场景的 **Total PSS**,观察内存波动
|
||||||
|
|
||||||
|
## 文件清单
|
||||||
|
|
||||||
|
EOF
|
||||||
|
|
||||||
|
for s in month_browse collapse_expand year_view year_select today_jump menu_toggle legal_holiday tools about licenses all_activities; do
|
||||||
|
local trace report
|
||||||
|
trace=$(ls -t "${LOGS_DIR}"/trace_*"_${s}".perfetto-trace 2>/dev/null | head -1)
|
||||||
|
report=$(ls -t "${LOGS_DIR}"/report_*"_${s}".md 2>/dev/null | head -1)
|
||||||
|
if [ -n "$trace" ]; then
|
||||||
|
echo "- \`$(basename "$trace")\` + \`$(basename "$report")\` — ${s}" >> "$summary_file"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "" >> "$summary_file"
|
||||||
|
echo "---" >> "$summary_file"
|
||||||
|
echo "生成时间: $(date '+%Y-%m-%d %H:%M:%S')" >> "$summary_file"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "========================================"
|
||||||
|
echo " 批量录制完成!"
|
||||||
|
echo "========================================"
|
||||||
|
echo ""
|
||||||
|
echo "汇总报告: ${summary_file}"
|
||||||
|
echo ""
|
||||||
|
}
|
||||||
|
|
||||||
|
# ──────────────────────────────────────────
|
||||||
|
# 如果是 --all 模式,直接执行批量录制
|
||||||
|
# ──────────────────────────────────────────
|
||||||
|
if [ "$RUN_ALL" = true ]; then
|
||||||
|
run_all_scenarios
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ──────────────────────────────────────────
|
||||||
|
# 场景准备
|
||||||
|
# ──────────────────────────────────────────
|
||||||
|
if [ -n "$SCENARIO" ]; then
|
||||||
|
run_scenario "$SCENARIO"
|
||||||
|
else
|
||||||
|
# 默认场景:仅启动应用
|
||||||
if [ "$NO_LAUNCH" = false ]; then
|
if [ "$NO_LAUNCH" = false ]; then
|
||||||
echo ""
|
echo ""
|
||||||
echo "[1/5] 启动应用..."
|
echo "[1/5] 启动应用..."
|
||||||
adb shell am start -n "${PACKAGE}/${ACTIVITY}" >/dev/null 2>&1 || true
|
adb shell am start -n "${PACKAGE}/${MAIN_ACTIVITY}" >/dev/null 2>&1 || true
|
||||||
sleep 2
|
sleep 2
|
||||||
else
|
else
|
||||||
echo ""
|
echo ""
|
||||||
echo "[1/5] 跳过启动 (--no-launch)"
|
echo "[1/5] 跳过启动 (--no-launch)"
|
||||||
fi
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 如果不是自动场景,给用户一点准备时间
|
||||||
|
if [ -n "$SCENARIO" ] && [ "$SCENARIO" = "full_flow" ] || [ "$SCENARIO" = "date_select" ] || [ "$SCENARIO" = "cross_month" ] || [ "$SCENARIO" = "date_checker" ]; then
|
||||||
|
echo ""
|
||||||
|
echo "准备开始 trace,请在倒计时结束后立即操作..."
|
||||||
|
for i in 3 2 1; do
|
||||||
|
echo " $i..."
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ──────────────────────────────────────────
|
||||||
# 抓取 Perfetto trace
|
# 抓取 Perfetto trace
|
||||||
|
# ──────────────────────────────────────────
|
||||||
echo ""
|
echo ""
|
||||||
echo "[2/5] 抓取 Perfetto trace (${DURATION_SEC}s)..."
|
echo "[2/5] 抓取 Perfetto trace (${DURATION_SEC}s)..."
|
||||||
|
if [ -n "$SCENARIO" ]; then
|
||||||
|
echo " 场景: ${SCENARIO_NAME}"
|
||||||
|
echo " 自动操作已启动,请按提示完成手动操作..."
|
||||||
|
else
|
||||||
echo " 请在设备上操作应用,trace 正在记录..."
|
echo " 请在设备上操作应用,trace 正在记录..."
|
||||||
|
fi
|
||||||
|
|
||||||
TRACE_FILE="/data/misc/perfetto-traces/yaya_${TIMESTAMP}.perfetto-trace"
|
TRACE_FILE="/data/misc/perfetto-traces/yaya_${TIMESTAMP}${SCENARIO_SUFFIX}.perfetto-trace"
|
||||||
LOCAL_TRACE="${LOGS_DIR}/trace_${TIMESTAMP}.perfetto-trace"
|
LOCAL_TRACE="${LOGS_DIR}/trace_${TIMESTAMP}${SCENARIO_SUFFIX}.perfetto-trace"
|
||||||
LOCAL_CONFIG="${LOGS_DIR}/.perfetto_config_${TIMESTAMP}.txt"
|
LOCAL_CONFIG="${LOGS_DIR}/.perfetto_config_${TIMESTAMP}${SCENARIO_SUFFIX}.txt"
|
||||||
DEVICE_CONFIG="/data/misc/perfetto-configs/yaya_config_${TIMESTAMP}.txt"
|
DEVICE_CONFIG="/data/misc/perfetto-configs/yaya_config_${TIMESTAMP}${SCENARIO_SUFFIX}.txt"
|
||||||
|
|
||||||
# 生成本地配置文件,然后 push 到设备
|
# 生成本地配置文件,然后 push 到设备
|
||||||
cat > "${LOCAL_CONFIG}" <<EOF
|
cat > "${LOCAL_CONFIG}" <<EOF
|
||||||
@ -172,22 +830,27 @@ echo " 拉取 trace 文件..."
|
|||||||
adb pull "${TRACE_FILE}" "${LOCAL_TRACE}"
|
adb pull "${TRACE_FILE}" "${LOCAL_TRACE}"
|
||||||
adb shell "rm -f ${TRACE_FILE}" || true
|
adb shell "rm -f ${TRACE_FILE}" || true
|
||||||
|
|
||||||
|
# 等待后台操作完成
|
||||||
|
cleanup_bg
|
||||||
|
|
||||||
# 抓取帧统计
|
# 抓取帧统计
|
||||||
echo ""
|
echo ""
|
||||||
echo "[3/5] 抓取帧统计..."
|
echo "[3/5] 抓取帧统计..."
|
||||||
FRAMESTATS_FILE="${LOGS_DIR}/framestats_${TIMESTAMP}.txt"
|
FRAMESTATS_FILE="${LOGS_DIR}/framestats_${TIMESTAMP}${SCENARIO_SUFFIX}.txt"
|
||||||
adb shell dumpsys gfxinfo "${PACKAGE}" framestats > "${FRAMESTATS_FILE}"
|
adb shell dumpsys gfxinfo "${PACKAGE}" framestats > "${FRAMESTATS_FILE}"
|
||||||
|
|
||||||
# 抓取内存信息
|
# 抓取内存信息
|
||||||
echo ""
|
echo ""
|
||||||
echo "[4/5] 抓取内存信息..."
|
echo "[4/5] 抓取内存信息..."
|
||||||
MEMINFO_FILE="${LOGS_DIR}/meminfo_${TIMESTAMP}.txt"
|
MEMINFO_FILE="${LOGS_DIR}/meminfo_${TIMESTAMP}${SCENARIO_SUFFIX}.txt"
|
||||||
adb shell dumpsys meminfo "${PACKAGE}" > "${MEMINFO_FILE}"
|
adb shell dumpsys meminfo "${PACKAGE}" > "${MEMINFO_FILE}"
|
||||||
|
|
||||||
|
# ──────────────────────────────────────────
|
||||||
# 生成报告摘要
|
# 生成报告摘要
|
||||||
|
# ──────────────────────────────────────────
|
||||||
echo ""
|
echo ""
|
||||||
echo "[5/5] 生成摘要..."
|
echo "[5/5] 生成摘要..."
|
||||||
REPORT_FILE="${LOGS_DIR}/report_${TIMESTAMP}.md"
|
REPORT_FILE="${LOGS_DIR}/report_${TIMESTAMP}${SCENARIO_SUFFIX}.md"
|
||||||
|
|
||||||
# 计算帧率相关数据
|
# 计算帧率相关数据
|
||||||
FRAME_COUNT=$(grep -c "FrameTimeline" "${FRAMESTATS_FILE}" 2>/dev/null || echo "0")
|
FRAME_COUNT=$(grep -c "FrameTimeline" "${FRAMESTATS_FILE}" 2>/dev/null || echo "0")
|
||||||
@ -210,7 +873,7 @@ APP_VERSION=$(adb shell dumpsys package "${PACKAGE}" | grep versionName | head -
|
|||||||
DEVICE_MODEL=$(adb shell getprop ro.product.model 2>/dev/null | tr -d '\r')
|
DEVICE_MODEL=$(adb shell getprop ro.product.model 2>/dev/null | tr -d '\r')
|
||||||
ANDROID_VERSION=$(adb shell getprop ro.build.version.release 2>/dev/null | tr -d '\r')
|
ANDROID_VERSION=$(adb shell getprop ro.build.version.release 2>/dev/null | tr -d '\r')
|
||||||
|
|
||||||
# 获取内存摘要($NF 取最后一个字段,避免中间空格导致的列错位)
|
# 获取内存摘要
|
||||||
TOTAL_PSS=$(awk '/TOTAL PSS:/{print $3; exit}' "${MEMINFO_FILE}")
|
TOTAL_PSS=$(awk '/TOTAL PSS:/{print $3; exit}' "${MEMINFO_FILE}")
|
||||||
JAVA_HEAP=$(awk '/^ *Java Heap:/{print $3; exit}' "${MEMINFO_FILE}")
|
JAVA_HEAP=$(awk '/^ *Java Heap:/{print $3; exit}' "${MEMINFO_FILE}")
|
||||||
NATIVE_HEAP=$(awk '/^ *Native Heap:/{print $3; exit}' "${MEMINFO_FILE}")
|
NATIVE_HEAP=$(awk '/^ *Native Heap:/{print $3; exit}' "${MEMINFO_FILE}")
|
||||||
@ -224,15 +887,27 @@ cat > "${REPORT_FILE}" <<EOF
|
|||||||
**应用版本:** ${APP_VERSION}
|
**应用版本:** ${APP_VERSION}
|
||||||
**构建类型:** $([ "$USE_TRACE_BUILD" = true ] && echo "trace" || echo "debug")
|
**构建类型:** $([ "$USE_TRACE_BUILD" = true ] && echo "trace" || echo "debug")
|
||||||
**追踪时长:** ${DURATION_SEC}s
|
**追踪时长:** ${DURATION_SEC}s
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# 场景信息
|
||||||
|
if [ -n "$SCENARIO" ]; then
|
||||||
|
cat >> "${REPORT_FILE}" <<EOF
|
||||||
|
**场景:** ${SCENARIO}
|
||||||
|
**场景名称:** ${SCENARIO_NAME}
|
||||||
|
**场景说明:** ${SCENARIO_DESC}
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
|
||||||
|
cat >> "${REPORT_FILE}" <<EOF
|
||||||
|
|
||||||
## 文件清单
|
## 文件清单
|
||||||
|
|
||||||
| 文件 | 说明 |
|
| 文件 | 说明 |
|
||||||
|------|------|
|
|------|------|
|
||||||
| \`trace_${TIMESTAMP}.perfetto-trace\` | Perfetto trace(在 https://ui.perfetto.dev 中打开) |
|
| \`trace_${TIMESTAMP}${SCENARIO_SUFFIX}.perfetto-trace\` | Perfetto trace(在 https://ui.perfetto.dev 中打开) |
|
||||||
| \`framestats_${TIMESTAMP}.txt\` | GPU 帧统计 |
|
| \`framestats_${TIMESTAMP}${SCENARIO_SUFFIX}.txt\` | GPU 帧统计 |
|
||||||
| \`meminfo_${TIMESTAMP}.txt\` | 内存快照 |
|
| \`meminfo_${TIMESTAMP}${SCENARIO_SUFFIX}.txt\` | 内存快照 |
|
||||||
| \`report_${TIMESTAMP}.md\` | 本报告 |
|
| \`report_${TIMESTAMP}${SCENARIO_SUFFIX}.md\` | 本报告 |
|
||||||
|
|
||||||
## 帧率摘要
|
## 帧率摘要
|
||||||
|
|
||||||
@ -256,8 +931,101 @@ cat > "${REPORT_FILE}" <<EOF
|
|||||||
| Java Heap | ${JAVA_HEAP} |
|
| Java Heap | ${JAVA_HEAP} |
|
||||||
| Native Heap | ${NATIVE_HEAP} |
|
| Native Heap | ${NATIVE_HEAP} |
|
||||||
| Graphics | ${GRAPHICS} |
|
| Graphics | ${GRAPHICS} |
|
||||||
|
EOF
|
||||||
|
|
||||||
## Perfetto 分析指南
|
# 场景特有分析指南
|
||||||
|
if [ -n "$SCENARIO" ]; then
|
||||||
|
cat >> "${REPORT_FILE}" <<EOF
|
||||||
|
|
||||||
|
## 场景分析指南
|
||||||
|
|
||||||
|
本报告对应场景: **${SCENARIO_NAME}**
|
||||||
|
|
||||||
|
### 在 Perfetto UI 中重点查看:
|
||||||
|
EOF
|
||||||
|
|
||||||
|
case "$SCENARIO" in
|
||||||
|
month_browse)
|
||||||
|
cat >> "${REPORT_FILE}" <<EOF
|
||||||
|
- \`CalendarPager:Page:*\` — 各月分页重组耗时分布
|
||||||
|
- \`MonthView:Compose\` — 月视图整体重组频率
|
||||||
|
- \`getMonthDays:*\` — 月份网格计算耗时
|
||||||
|
- 对比不同月份页面的 \`max_ms\`,找出重组最慢的月份
|
||||||
|
EOF
|
||||||
|
;;
|
||||||
|
date_select)
|
||||||
|
cat >> "${REPORT_FILE}" <<EOF
|
||||||
|
- \`DayCell\` — 单个日期单元格重组(通过 transition label)
|
||||||
|
- \`MonthView:Compose\` — 日期选中触发的整页重组
|
||||||
|
- \`AnimatedGif\` 相关 trace(如果存在)— 选中动画
|
||||||
|
- 查找是否有连续多帧超过 16.67ms(选中动画期间)
|
||||||
|
EOF
|
||||||
|
;;
|
||||||
|
collapse_expand)
|
||||||
|
cat >> "${REPORT_FILE}" <<EOF
|
||||||
|
- \`VM:collapseProgress\` — 折叠动画状态更新频率和耗时
|
||||||
|
- \`CalendarPagerArea\` — 区域重组(月↔周切换时的布局变化)
|
||||||
|
- \`WeekPager:Page:*\` — 周视图出现时的重组
|
||||||
|
- 观察 \`collapseProgress\` 与帧数据的对应关系
|
||||||
|
EOF
|
||||||
|
;;
|
||||||
|
year_view|year_select)
|
||||||
|
cat >> "${REPORT_FILE}" <<EOF
|
||||||
|
- \`MonthView→YearView\` / \`YearView→MonthView\` — 转场 trace
|
||||||
|
- \`YearView:Compose\` — 年视图整体重组
|
||||||
|
- \`YearGridView:*\` — 年视图网格重组
|
||||||
|
- \`generateMiniMonthDays:*\` — 迷你月日期计算
|
||||||
|
- 对比转场前后 500ms 的帧率变化
|
||||||
|
EOF
|
||||||
|
;;
|
||||||
|
menu_toggle)
|
||||||
|
cat >> "${REPORT_FILE}" <<EOF
|
||||||
|
- 查找 AnimatedVisibility 相关的重组 slice
|
||||||
|
- \`MonthView:Compose\` — 菜单开关是否触发整页重组
|
||||||
|
- 观察菜单动画期间的帧率是否稳定
|
||||||
|
EOF
|
||||||
|
;;
|
||||||
|
legal_holiday)
|
||||||
|
cat >> "${REPORT_FILE}" <<EOF
|
||||||
|
- \`DayCell\` — 大规模重组(所有日期单元格可能同时重组)
|
||||||
|
- 查找 staggered 动画相关的 trace(delay=cellIndex*15)
|
||||||
|
- 对比开关前后的 \`MonthView:Compose\` 重组次数
|
||||||
|
EOF
|
||||||
|
;;
|
||||||
|
tools|about|licenses|date_checker)
|
||||||
|
cat >> "${REPORT_FILE}" <<EOF
|
||||||
|
- 查看对应 Activity 启动时的 Choreographer#doFrame 帧数据
|
||||||
|
- \`MonthView:Compose\`(如从主页面跳转)— 转场期间的重组
|
||||||
|
- Activity 转场动画期间的帧率稳定性
|
||||||
|
EOF
|
||||||
|
;;
|
||||||
|
full_flow)
|
||||||
|
cat >> "${REPORT_FILE}" <<EOF
|
||||||
|
- 分段分析:按时间轴对应不同操作阶段
|
||||||
|
- 标记出各阶段切换时的帧率变化
|
||||||
|
- \`MonthView→YearView\`、\`YearView→MonthView\` 等转场标记
|
||||||
|
- 整体评估哪些操作阶段掉帧最严重
|
||||||
|
EOF
|
||||||
|
;;
|
||||||
|
all_activities)
|
||||||
|
cat >> "${REPORT_FILE}" <<EOF
|
||||||
|
- 按时间分段,对应不同 Activity 启动阶段
|
||||||
|
- 比较各 Activity 启动时的首帧耗时
|
||||||
|
- 观察 Activity 转场动画(slide_in_right)期间的帧率
|
||||||
|
EOF
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
cat >> "${REPORT_FILE}" <<EOF
|
||||||
|
- 查看本场景相关的自定义 trace 标记
|
||||||
|
- 分析对应时间段的帧率数据
|
||||||
|
EOF
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
cat >> "${REPORT_FILE}" <<EOF
|
||||||
|
|
||||||
|
## 通用 Perfetto 分析指南
|
||||||
|
|
||||||
打开 [Perfetto UI](https://ui.perfetto.dev),上传 trace 文件:
|
打开 [Perfetto UI](https://ui.perfetto.dev),上传 trace 文件:
|
||||||
|
|
||||||
@ -286,40 +1054,29 @@ cat > "${REPORT_FILE}" <<EOF
|
|||||||
- \`DayCell\` — 单个日期单元格(通过 transition label)
|
- \`DayCell\` — 单个日期单元格(通过 transition label)
|
||||||
|
|
||||||
### 2. 分析帧率
|
### 2. 分析帧率
|
||||||
在 \`framestats_${TIMESTAMP}.txt\` 中查看:
|
在 \`framestats_${TIMESTAMP}${SCENARIO_SUFFIX}.txt\` 中查看:
|
||||||
- \`FrameTimeline\` 行 — 每帧的 CPU/GPU 耗时
|
- \`FrameTimeline\` 行 — 每帧的 CPU/GPU 耗时
|
||||||
- \`jank\` 标记 — 掉帧情况
|
- \`jank\` 标记 — 掉帧情况
|
||||||
|
|
||||||
### 3. 内存分析
|
### 3. 内存分析
|
||||||
在 \`meminfo_${TIMESTAMP}.txt\` 中关注:
|
在 \`meminfo_${TIMESTAMP}${SCENARIO_SUFFIX}.txt\` 中关注:
|
||||||
- \`TOTAL\` 行 — 应用总内存占用
|
- \`TOTAL\` 行 — 应用总内存占用
|
||||||
- \`Graphics\` 行 — GPU 内存使用
|
- \`Graphics\` 行 — GPU 内存使用
|
||||||
- \`Native Heap\` 行 — 原生堆内存
|
- \`Native Heap\` 行 — 原生堆内存
|
||||||
|
|
||||||
### 4. 年月视图切换专项分析
|
|
||||||
|
|
||||||
在 Perfetto 中按以下步骤分析转场性能:
|
|
||||||
|
|
||||||
1. 找到 \`MonthView→YearView\` 或 \`YearView→MonthView\` 标记
|
|
||||||
2. 查看标记前后 500ms 的帧数据:
|
|
||||||
- 查找超过 16.67ms 的帧(Choreographer#doFrame)
|
|
||||||
- 检查是否有连续多帧超过预算
|
|
||||||
3. 同时搜索 \`MonthView:Compose\` 和 \`YearView:Compose\`,观察重组重叠情况
|
|
||||||
4. 查看 \`YearGridView:*\` 的耗时,年视图 12 个月网格的计算和绘制成本
|
|
||||||
|
|
||||||
## 基线对比方法
|
## 基线对比方法
|
||||||
|
|
||||||
要对比优化前后的性能:
|
要对比优化前后的性能:
|
||||||
|
|
||||||
\`\`\`bash
|
\`\`\`bash
|
||||||
# 1. 记录当前数据作为基线
|
# 1. 记录当前数据作为基线
|
||||||
./scripts/profile.sh --trace 15
|
$0 --scenario ${SCENARIO:-month_browse} --trace 15
|
||||||
|
|
||||||
# 2. 修改代码后重新编译
|
# 2. 修改代码后重新编译
|
||||||
./gradlew :app:installTrace
|
./gradlew :app:installTrace
|
||||||
|
|
||||||
# 3. 再次记录
|
# 3. 再次记录
|
||||||
./scripts/profile.sh --trace 15
|
$0 --scenario ${SCENARIO:-month_browse} --trace 15
|
||||||
|
|
||||||
# 4. 对比两个 report 中的帧率摘要表格
|
# 4. 对比两个 report 中的帧率摘要表格
|
||||||
\`\`\`
|
\`\`\`
|
||||||
@ -336,8 +1093,16 @@ echo " framestats: ${FRAMESTATS_FILE}"
|
|||||||
echo " meminfo: ${MEMINFO_FILE}"
|
echo " meminfo: ${MEMINFO_FILE}"
|
||||||
echo " report: ${REPORT_FILE}"
|
echo " report: ${REPORT_FILE}"
|
||||||
echo ""
|
echo ""
|
||||||
|
if [ -n "$SCENARIO" ]; then
|
||||||
|
echo "场景: ${SCENARIO_NAME}"
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
echo "下一步:"
|
echo "下一步:"
|
||||||
echo " 1. 打开 https://ui.perfetto.dev"
|
echo " 1. 打开 https://ui.perfetto.dev"
|
||||||
echo " 2. 上传 trace_${TIMESTAMP}.perfetto-trace"
|
echo " 2. 上传 trace_${TIMESTAMP}${SCENARIO_SUFFIX}.perfetto-trace"
|
||||||
|
if [ -n "$SCENARIO" ]; then
|
||||||
|
echo " 3. 搜索场景相关的 trace 标记进行分析"
|
||||||
|
else
|
||||||
echo " 3. 搜索 'MonthView→YearView' 查看转场 trace"
|
echo " 3. 搜索 'MonthView→YearView' 查看转场 trace"
|
||||||
|
fi
|
||||||
echo ""
|
echo ""
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user