#!/bin/bash # # YaYa 性能追踪脚本 # 使用 Perfetto 抓取应用 trace,保存到 logs/ 目录 # # 用法: # ./scripts/profile.sh # 默认抓取 8 秒 # ./scripts/profile.sh 15 # 抓取 15 秒 # ./scripts/profile.sh --no-launch # 不自动启动应用(应用已在运行) # ./scripts/profile.sh --trace # 使用 trace 构建类型(保留自定义 trace 标记) # set -euo pipefail PACKAGE="plus.rua.project" ACTIVITY="plus.rua.project.MainActivity" PROJECT_ROOT="$(cd "$(dirname "$0")/.." && pwd)" LOGS_DIR="${PROJECT_ROOT}/logs" # 解析参数 DURATION_SEC=8 NO_LAUNCH=false USE_TRACE_BUILD=false for arg in "$@"; do case "$arg" in --no-launch) NO_LAUNCH=true ;; --trace) USE_TRACE_BUILD=true ;; --help|-h) echo "用法: $0 [秒数] [--no-launch] [--trace]" echo "" echo "选项:" echo " 秒数 抓取时长(默认 8 秒)" echo " --no-launch 不自动启动应用" echo " --trace 使用 trace 构建(release 优化 + 保留 trace 标记)" echo " --help 显示此帮助" exit 0 ;; [0-9]*) DURATION_SEC="$arg" ;; esac done DURATION_MS=$((DURATION_SEC * 1000)) TIMESTAMP=$(date +%Y%m%d_%H%M%S) echo "========================================" echo " YaYa 性能追踪" echo " 包名: ${PACKAGE}" echo " 时长: ${DURATION_SEC}s" echo " 构建: $([ "$USE_TRACE_BUILD" = true ] && echo "trace (release + trace)" || echo "debug")" echo " 输出: ${LOGS_DIR}/" echo "========================================" # 创建 logs 目录 mkdir -p "${LOGS_DIR}" # 检查 adb if ! command -v adb &>/dev/null; then echo "错误: adb 未找到。请确保 Android SDK 的 platform-tools 在 PATH 中。" exit 1 fi # 检查设备连接 DEVICE_COUNT=$(adb devices | grep -c "device$" || true) if [ "$DEVICE_COUNT" -eq 0 ]; then echo "错误: 没有已连接的 Android 设备。" exit 1 fi if [ "$DEVICE_COUNT" -gt 1 ]; then echo "警告: 检测到多个设备,将使用默认设备。" fi # 检查应用是否已安装 if ! adb shell pm list packages | grep -q "${PACKAGE}"; then echo "错误: 应用 ${PACKAGE} 未安装。请先运行 ./gradlew :app:installDebug" if [ "$USE_TRACE_BUILD" = true ]; then echo " 或使用 ./gradlew :app:installTrace 安装 trace 构建" fi exit 1 fi # 启动应用(如果未禁用) if [ "$NO_LAUNCH" = false ]; then echo "" echo "[1/5] 启动应用..." adb shell am start -n "${PACKAGE}/${ACTIVITY}" >/dev/null 2>&1 || true sleep 2 else echo "" echo "[1/5] 跳过启动 (--no-launch)" fi # 抓取 Perfetto trace echo "" echo "[2/5] 抓取 Perfetto trace (${DURATION_SEC}s)..." echo " 请在设备上操作应用,trace 正在记录..." TRACE_FILE="/data/misc/perfetto-traces/yaya_${TIMESTAMP}.perfetto-trace" LOCAL_TRACE="${LOGS_DIR}/trace_${TIMESTAMP}.perfetto-trace" LOCAL_CONFIG="${LOGS_DIR}/.perfetto_config_${TIMESTAMP}.txt" DEVICE_CONFIG="/data/misc/perfetto-configs/yaya_config_${TIMESTAMP}.txt" # 生成本地配置文件,然后 push 到设备 cat > "${LOCAL_CONFIG}" < /dev/null rm -f "${LOCAL_CONFIG}" # 运行 perfetto(前台阻塞,直到 duration_ms 结束) adb shell "perfetto --txt -c ${DEVICE_CONFIG} -o ${TRACE_FILE}" # 清理设备上的临时配置文件 adb shell "rm -f ${DEVICE_CONFIG}" # 拉取 trace 文件 echo " 拉取 trace 文件..." adb pull "${TRACE_FILE}" "${LOCAL_TRACE}" adb shell "rm -f ${TRACE_FILE}" || true # 抓取帧统计 echo "" echo "[3/5] 抓取帧统计..." FRAMESTATS_FILE="${LOGS_DIR}/framestats_${TIMESTAMP}.txt" adb shell dumpsys gfxinfo "${PACKAGE}" framestats > "${FRAMESTATS_FILE}" # 抓取内存信息 echo "" echo "[4/5] 抓取内存信息..." MEMINFO_FILE="${LOGS_DIR}/meminfo_${TIMESTAMP}.txt" adb shell dumpsys meminfo "${PACKAGE}" > "${MEMINFO_FILE}" # 生成报告摘要 echo "" echo "[5/5] 生成摘要..." REPORT_FILE="${LOGS_DIR}/report_${TIMESTAMP}.md" # 计算帧率相关数据 FRAME_COUNT=$(grep -c "FrameTimeline" "${FRAMESTATS_FILE}" 2>/dev/null || echo "0") # 从 gfxinfo 提取关键指标 TOTAL_FRAMES=$(grep "Total frames rendered:" "${FRAMESTATS_FILE}" | tail -1 | awk '{print $4}' || echo "N/A") JANKY_FRAMES=$(grep "Janky frames:" "${FRAMESTATS_FILE}" | tail -1 | awk '{print $3}' || echo "N/A") JANKY_PERCENT=$(grep "Janky frames:" "${FRAMESTATS_FILE}" | tail -1 | grep -oP '\(\K[^)]+' || echo "N/A") P50=$(grep "50th percentile:" "${FRAMESTATS_FILE}" | tail -1 | awk '{print $3}' || echo "N/A") P90=$(grep "90th percentile:" "${FRAMESTATS_FILE}" | tail -1 | awk '{print $3}' || echo "N/A") P99=$(grep "99th percentile:" "${FRAMESTATS_FILE}" | tail -1 | awk '{print $3}' || echo "N/A") SLOW_UI=$(grep "Number Slow UI thread:" "${FRAMESTATS_FILE}" | tail -1 | awk '{print $4}' || echo "N/A") SLOW_DRAW=$(grep "Number Slow issue draw commands:" "${FRAMESTATS_FILE}" | tail -1 | awk '{print $5}' || echo "N/A") HIGH_INPUT=$(grep "Number High input latency:" "${FRAMESTATS_FILE}" | tail -1 | awk '{print $4}' || echo "N/A") # 获取应用版本 APP_VERSION=$(adb shell dumpsys package "${PACKAGE}" | grep versionName | head -1 | awk '{print $1}' | cut -d= -f2 2>/dev/null || echo "unknown") # 获取设备信息 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') # 获取内存摘要 TOTAL_PSS=$(grep "TOTAL PSS:" "${MEMINFO_FILE}" | awk '{print $3}' || echo "N/A") JAVA_HEAP=$(grep "Java Heap:" "${MEMINFO_FILE}" | head -1 | awk '{print $2}' || echo "N/A") NATIVE_HEAP=$(grep "Native Heap:" "${MEMINFO_FILE}" | head -1 | awk '{print $2}' || echo "N/A") GRAPHICS=$(grep "Graphics:" "${MEMINFO_FILE}" | head -1 | awk '{print $2}' || echo "N/A") cat > "${REPORT_FILE}" <