mcpField
I
ios-ettrace-performance

ios-ettrace-performance

github.com/openai开发7.7k89 次安装3 周前更新
代码仓库

关于 ios-ettrace-performance

一项用于采集和分析 iOS 模拟器应用符号化 ETTrace 性能数据的技能,指导开发者完成配置、保存追踪文件,并报告性能热点与注意事项。

主要功能

  1. 01采集单个聚焦应用流程
  2. 02为模拟器性能分析链接 ETTrace
  3. 03收集并验证匹配的 dSYM
  4. 04保存处理后的火焰图 JSON
  5. 05报告热点与分析注意事项

适用场景

  1. 01测量应用启动或首次渲染
  2. 02分析一次运行时交互
  3. 03检查已符号化的自有调用栈

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/openai/plugins --skill ios-ettrace-performance

安装后在 Claude Code 中输入/ios-ettrace-performance确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

agents/
openai.yaml
scripts/
analyze_flamegraph_json.py
collect_ios_dsyms.sh

详细介绍

iOS ETTrace 性能分析

使用此技能从 iOS 模拟器应用中采集聚焦且已符号化的 ETTrace 性能分析数据。如果任务还需要构建、安装、启动模拟器、驱动 UI、查看日志或截取屏幕截图,请搭配使用 ../ios-debugger-agent/SKILL.md。

核心工作流

  1. 选择一个聚焦的流程,并记下预期的开始和结束节点。
  2. 构建将要安装并进行性能分析的确切模拟器应用。
  3. 临时将 ETTrace 链接到该应用目标,以便进行模拟器/调试性能分析。
  4. 收集与 UUID 匹配的应用可执行文件和内嵌动态框架的 dSYM。
  5. 采集一次启动或运行时跟踪。
  6. 运行后立即保留处理后的火焰图 JSON。
  7. 仅分析处理后的 JSON,并报告流程、产物、热点和注意事项。

避免进行宽泛的“使用应用一段时间”式采集。一次跟踪应对应一个用户可见的流程。

设置

为每次性能分析会话使用一个可写的运行目录:

if [ -z "${RUN_DIR:-}" ]; then
  RUN_DIR="$(mktemp -d "${TMPDIR:-/tmp}/codex-ios-ettrace.XXXXXX")"
fi
mkdir -p "$RUN_DIR"

如果尚未安装 ETTrace runner CLI,请安装:

brew install emergetools/homebrew-tap/ettrace

ettrace 是运行于 macOS 主机端的 runner。应用还必须链接适用于 iOS Simulator 架构的 ETTrace.xcframework。 此工作流已针对 ETTrace v1.1.0 处理后的顶层包含 nodes 的 output_<thread>.json 文件进行验证。

将 ETTrace 链接到应用

将 ETTrace 接入正在进行性能分析的确切应用目标。将此集成保留为明确的临时补丁,性能分析任务完成后将其移除,除非用户明确要求保留。

优先选择以下方式:

  • 如果仓库已有适用于模拟器的 ETTrace.xcframework,则复用该版本。
  • 如果没有,则从上游 ETTrace 软件包构建仅适用于模拟器的副本,并放入 RUN_DIR。
  • 将框架直接链接到应用目标,而不只是链接到测试、资源、数据文件或嵌套的启动器目标。
  • 确认启动日志会打印 Starting ETTrace。
  • 一次只对一个已插桩 ETTrace 的模拟器应用进行性能分析,因为模拟器模式会监听固定的 localhost 端口。

需要时构建模拟器框架:

ETTRACE_TAG="${ETTRACE_TAG:-v1.1.0}" # Override to match the installed runner when Homebrew updates.
ETTRACE_SRC="$RUN_DIR/ETTrace-src"
if [ ! -d "$ETTRACE_SRC" ]; then
  git clone --depth 1 --branch "$ETTRACE_TAG" https://github.com/EmergeTools/ETTrace "$ETTRACE_SRC"
fi

rm -rf "$RUN_DIR/ETTrace-iphonesimulator.xcarchive" "$RUN_DIR/ETTrace.xcframework"
pushd "$ETTRACE_SRC" >/dev/null
xcodebuild archive \
  -scheme ETTrace \
  -archivePath "$RUN_DIR/ETTrace-iphonesimulator.xcarchive" \
  -sdk iphonesimulator \
  -destination 'generic/platform=iOS Simulator' \
  BUILD_LIBRARY_FOR_DISTRIBUTION=YES \
  INSTALL_PATH='Library/Frameworks' \
  SKIP_INSTALL=NO \
  CLANG_CXX_LANGUAGE_STANDARD=c++17

xcodebuild -create-xcframework \
  -framework "$RUN_DIR/ETTrace-iphonesimulator.xcarchive/Products/Library/Frameworks/ETTrace.framework" \
  -output "$RUN_DIR/ETTrace.xcframework"
popd >/dev/null

对于 Bazel 应用,临时导入通常如下所示:

load("@rules_apple//apple:apple.bzl", "apple_dynamic_xcframework_import")

package(default_visibility = ["//visibility:public"])

apple_dynamic_xcframework_import(
    name = "ETTrace",
    xcframework_imports = glob(["ETTrace.xcframework/**"]),
)

对于 Xcode 项目,临时将适用于模拟器的 ETTrace.xcframework 添加到正在进行性能分析的调试模拟器构建的应用目标中的 Link Binary With Libraries / Embed Frameworks 阶段,然后在性能分析后移除该配置。

符号化检查

不要根据未符号化的火焰图得出结论。每次采集前,准备一个 dSYM 文件夹,其中包含应用 dSYM 以及所有内嵌的第一方动态框架 dSYM。

在生成已安装应用的最终构建完成后收集 dSYM:

SKILL_DIR="<absolute path to this loaded skill folder>"
APP="<path-to-built-simulator-App.app>"
DSYMS="$RUN_DIR/dsyms"

"$SKILL_DIR/scripts/collect_ios_dsyms.sh" \
  --app "$APP" \
  --out-dir "$DSYMS" \
  --search-root "$(dirname "$APP")" \
  --search-root "$PWD" \
  --extra-dsym "$RUN_DIR/ETTrace-iphonesimulator.xcarchive/dSYMs/ETTrace.framework.dSYM"

对于必须完成符号化的应用自有动态框架,添加 --require-framework <FrameworkName>;仅当所有内嵌框架均由应用所有或预计都具有符号时,才使用 --require-all-frameworks。如果辅助工具报告缺少必需的应用或框架 dSYM,请重新构建确切的模拟器应用并启用 dSYM 生成,然后再进行跟踪;或者将包含这些 dSYM 的构建输出目录添加为另一个 --search-root。

如果报告看起来可疑,请在跟踪前验证重要的 UUID:

dwarfdump --uuid "$APP/$(/usr/libexec/PlistBuddy -c 'Print :CFBundleExecutable' "$APP/Info.plist")"
find "$DSYMS" -maxdepth 1 -type d -name '*.dSYM' -print -exec dwarfdump --uuid {} \;

ETTrace 退出后,查看其符号化摘要。除非只是少量噪声,否则应将有意义的第一方“have library but no symbol”行视为跟踪失败。未符号化的系统框架或 ETTrace 内部分类通常可以接受。

采集

对于启动跟踪:

cd "$RUN_DIR"
CAPTURE_MARKER="$RUN_DIR/.ettrace-capture-start"
: > "$CAPTURE_MARKER"
find "$RUN_DIR" -maxdepth 1 \( -name 'output.json' -o -name 'output_*.json' \) -delete
ettrace --simulator --launch --verbose --dsyms "$DSYMS"

仅在测量启动或首次渲染时使用 --launch。首次启动时的连接可能会强制退出应用;如果系统提示,请从模拟器主屏幕重新启动,而不是从 Xcode 启动。对于安装后的首次启动跟踪,请暂时在应用的 Info.plist 中设置 ETTraceRunAtStartup=YES,然后运行 ettrace --simulator 并从主屏幕启动应用。

对于运行时流程跟踪:

cd "$RUN_DIR"
CAPTURE_MARKER="$RUN_DIR/.ettrace-capture-start"
: > "$CAPTURE_MARKER"
find "$RUN_DIR" -maxdepth 1 \( -name 'output.json' -o -name 'output_*.json' \) -delete
ettrace --simulator --verbose --dsyms "$DSYMS"

从稳定的界面开始,启动 ETTrace,执行一个明确聚焦的流程,等待所有可见操作完成,然后停止运行器。如需进行更广泛的归因分析,请添加 --multi-thread;否则从主线程开始。

在 Codex 中,使用 TTY 运行 ettrace,并通过 write_stdin 回答提示。没有 TTY 时,运行器可能会退出,无法生成有用的跟踪结果。

保留输出

下一次 ETTrace 运行可能会覆盖已处理的火焰图文件,因此请立即保留新生成的 output_<thread-id>.json 文件。不要分析保存的 output.json;ETTrace 也会提供一个名为该名称的查看器路由,而且原始的 emerge-output/output.json 文件并非此工作流所需的已处理火焰图产物。

PRESERVED_DIR="$(mktemp -d "$RUN_DIR/run-$(date +%Y%m%d-%H%M%S).XXXXXX")"
: > "$PRESERVED_DIR/summary.txt"
if [ ! -e "$CAPTURE_MARKER" ]; then
  echo "error: capture marker missing; start a fresh ETTrace capture before preserving outputs" >&2
  exit 1
fi
find "$RUN_DIR" -maxdepth 1 -name 'output_*.json' -newer "$CAPTURE_MARKER" -print | while IFS= read -r json; do
  preserved="$PRESERVED_DIR/${json##*/}"
  cp "$json" "$preserved"
  {
    echo "## ${preserved##*/}"
    python3 "$SKILL_DIR/scripts/analyze_flamegraph_json.py" "$preserved"
  } >> "$PRESERVED_DIR/summary.txt"
done
if [ ! -s "$PRESERVED_DIR/summary.txt" ]; then
  echo "error: no fresh processed ETTrace output JSON found in $RUN_DIR" >&2
  exit 1
fi

仅分析 RUN_DIR 中已处理的 output_*.json 文件。除非是在调试 ETTrace 本身,否则请忽略 output.json 和原始的 emerge-output/output.json 文件。如果分析器拒绝该 JSON 结构,请使用 Homebrew ETTrace 运行器和匹配的应用端 ETTrace.xcframework 标签重新采集,而不要尝试解读被拒绝的文件。

阅读性能分析结果

从 run-*/summary.txt 开始;如有需要,再直接检查已处理的 JSON。

报告:

  • 确切的流程、应用构建版本、模拟器型号和运行时,以及运行次数
  • 已处理的火焰图 JSON 文件路径
  • 活跃度最高的叶节点和包含样本权重或百分比的第一方调用栈
  • 应用自有二进制文件的符号是否完整
  • 首次运行设置、仅模拟器环境下的开销、网络波动或样本数量较少等注意事项
  • 仅当在可比设置下采集了相同流程时,才报告前后差异

清理

性能分析完成后,除非用户要求保留,否则请移除临时的 ETTrace 应用接入代码。根据当前任务决定保留或丢弃运行产物。

评论

支持 Markdown