外观
Perfowl 1.0.0 内部正式版发版
Owner 2026-11-03:在分版本能力表工作之前先发正式第一版;只发给公司内部同事试用,不对外发布;站点信息更新,下载按钮保持不可下载。2026-11-02 以来各项修改 Owner 已真机确认通过。
一、范围
- 版本 1.0.0,从推送到全部远程的 main 构建,内容等同内部包 251 + 本批文档;不夹带新功能。
- 卡顿(Hitch)只做逐帧数据保留与离线重算,界面不显示,不属于本版功能。
- 分版本能力表与自动判定排在发版之后(方案)。
二、发版门禁
| 项 | 要求 |
|---|---|
| 回归 | Python 全量(失败只能是既有 16 项环境基线);Swift 全量 0 失败 |
| 签名 | Developer ID Application 签名 App 与 DMG,codesign --verify --deep --strict |
| 公证 | 提交 Apple Notary Service 成功、ticket stapling、stapler validate、spctl Gatekeeper 接受(此前内部包按 Owner 决定暂缓,本版必须完成) |
| 安装 | 独立解包核对、本机同址安装、启动器唯一 |
| 校验 | DMG SHA-256 |
| 标签 | v1.0.0 指向发版提交,推送 GitHub 与 GitLab |
| 站点 | 下载页与首页写明 1.0.0 内部版已发布、仅限公司内部;不提供下载链接与安装包 |
构建脚本改动(发版前必需):build-app.sh 目前给包内 329 个嵌套二进制签名时不带可信时间戳(--timestamp=none,为内部包打包快),而 Apple 公证要求每个二进制都带时间戳,照现状提交会被拒。新增环境变量 PERFOWL_NESTED_TIMESTAMP=1:嵌套二进制改用 --timestamp(预计多 3–6 分钟,仅发版用,内部包不变);PERFOWL_RELEASE_CHANNEL 写入 PerfowlReleaseChannel(默认仍为 internal-beta,本版为 internal-release)。首次发版构建(d1d417b0)在第 300 余个二进制处遇到时间戳服务未返回时间戳(“A timestamp was expected but was not found”)而失败,于是每个嵌套签名最多重试 3 次、间隔 2 秒;第二次构建(624ccfc5)在第 109 个二进制处 3 次均报 “The timestamp service is not available”,随后单独测试服务已恢复,判断为间歇性不可用或限流(推断),改为指数退避最多 6 次(2/4/8/16/32 秒,累计约 1 分钟),仍失败才终止。公证流程:App 打 zip 提交 → stapling App → 用已 stapling 的 App 做 DMG → 签名 DMG → 提交 DMG → stapling DMG。
GPL-3.0:本版仅公司内部分发,不触发对外分发的法务门禁;对外发布前仍须正式法务结论。
三、发版说明(给内部同事)
能做什么
- 无侵入测试 iPhone 上任意 App 的性能:不改包、不重签、不注入。
- 实时指标:截图、启动耗时、FPS、帧耗时、显示性能、CPU(进程 / 整机 / 每核)、内存、GPU、线程、上下文切换、唤醒、磁盘、温度、网络(进程 / 整机)、电池(Wi-Fi 连接且未外接供电时)、能耗、GPU Counter。
- 会话本地保存,可回看、导出报告(PDF / 表格)与多会话对比。
- 工具箱:设备信息;应用管理(导入 IPA、卸载、查看与导出应用文件、签名类型标识);崩溃日志导出与删除。
使用要求与已知限制
- macOS 13 及以上;双架构(Intel 与 Apple 芯片原生运行)。
- 真机验证以单台 iOS 26 设备为主;iOS 16、17.0、18.2 有连接与基础指标证据;iOS 15、17.4+ 等版本未逐项验证,见能力表计划。
- 部分指标仍为候选口径(与 PerfDog 未逐项校准),报告中按原样标注;缺失值显示为空,不显示为 0。
- 测试中被测 App 不能在工具箱中卸载。
四、执行记录
(发版完成后追加:提交号、DMG、SHA-256、公证提交号与结果、Gatekeeper、安装与启动器、标签、站点核对。)
方案变更 · 2026-11-03:改为双架构(Intel + Apple 芯片)
Owner 要求 1.0.0 为双架构包。已构建的 Intel 单架构候选(build 252,4d82ac67)不作为正式版。
可行性(E2):本机(Intel)swift build -c release --arch arm64 --arch x86_64 230 秒完成,主程序同时含 x86_64 与 arm64。三个 Python 冻结组件(pymobiledevice3、采集器、采集核心)PyInstaller 只能在同架构主机上冻结,必须在 Apple 芯片 Mac 上完成;该流程已于 2026-10-18 在 Apple 芯片主机跑通(ARM 冻结方案),运行时按 Tools/<arch> 选择组件。
分工:
- Apple 芯片主机上的 AI(Implementation 角色)从指定 main 提交执行
MacApp/scripts/build-app.sh(不签名,ad-hoc),只取产物中的Contents/Resources/Tools/arm64/与Contents/Resources/Licenses/libusb-LGPL-2.1.txt,连同清单打包为perfowl-arm64-tools-<提交前 8 位>.tar.gz,上传到 GitHub 私有仓库的草稿 Release(gh release create arm64-tools-<提交前 8 位> --draft),不进 git 历史(约 230 MB 二进制不应永久进入两个远程的历史);不推送任何代码修改。 - 本机下载该附件,核对清单与架构,
build-app.sh新增双架构模式组装:主程序 universal、Tools/x86_64本机冻结、Tools/arm64取自附件;全部用 Developer ID 重新签名(带时间戳),公证、stapling、Gatekeeper。 - 附件对应提交与发版提交之间,
MacApp/Sidecar与冻结脚本必须无差异,否则拒绝组装。 - 发版前 Owner 在 Apple 芯片 Mac 与 Intel Mac 上各实测一次(E4)。
清单 manifest.json 字段:sourceCommit、hostArch、macOS、python、pymobiledevice3、pyinstaller、每个文件的相对路径 / 字节 / SHA-256、三个组件的实际运行检查输出(perfowl_collector_core probe、pymobiledevice3 version、perfowl_collector --help 退出码)、Mach-O 架构统计。不写主机名、用户名、设备标识。
公证凭据:Owner 要求由 Claude 保存。Claude 没有账号密码;为免密码进入对话记录,请 Owner 提供 App Store Connect API 密钥文件(.p8)路径与 Key ID、Issuer ID,由 Claude 以 notarytool store-credentials --key 存入本机钥匙串,密钥内容不进入仓库、日志或对话。
Implementation Update · 2026-11-03:双架构组装模式
build-app.sh 新增 PERFOWL_ARM64_TOOLS_DIR(指向解开的 arm64 附件,含 Tools/arm64、Licenses/libusb-LGPL-2.1.txt、manifest.json):
- 只允许在 Intel 主机上组装;读取清单
sourceCommit,该提交须在本地仓库,且与当前提交在MacApp/Sidecar与MacApp/scripts(除build-app.sh本身)上无差异,否则拒绝; - Swift 以
--arch arm64 --arch x86_64构建,主程序必须同时含两种架构; Tools/x86_64照旧本机冻结,Tools/arm64用ditto原样复制(保留符号链接),其中每个 Mach-O 必须只含 arm64;- Info.plist 新增
PerfowlArchitectures、PerfowlArm64ToolsCommit;签名循环覆盖两套组件,arm64 的 ad-hoc 签名被 Developer ID(带时间戳)替换。
验证(E2,未签名本机实验构建):缺附件 → 拒绝;清单提交为 f14465c7(Sidecar 不同)→ 拒绝;arm64 目录混入 Intel 二进制 → 在主程序双架构检查通过后拒绝。首次运行时双架构判断写法有误(相邻架构名共用空格导致误判),已改为逐词判断并复测通过。正向组装待 arm64 附件到位。
公证凭据:按 Owner 要求检索项目记录,未找到已配置的凭据——build 50–52 验收记录均为 notaryCredentialProfileAvailable: false,2026-10-18 迁移交接写明“恢复正式交付时安全配置 notary 凭据,不从旧日志抽取密码”,私有构建目录无相关配置。仍需 Owner 提供。
Validation Update · 2026-11-03:Apple 芯片主机首次构建失败与调整
Apple 芯片主机(macOS 15.3.1、Swift 6.1.2)从 b236168a 运行 build-app.sh,34 秒后在 swift build 失败:SessionReportView.swift:160 的 overview(_:) 视图表达式“unable to type-check this expression in reasonable time”。本机 Xcode 的 Swift 版本可编译同一源码(双架构 230 秒通过),判断为较旧 Swift 6.1.2 类型推断超时(推断)。ARM 冻结环境(Python 3.12.10、PyInstaller 6.22.3、pymobiledevice3 11.3.1、libusb 1.0.29)完好,单独冻结 pymobiledevice3 成功。
调整:Apple 芯片主机不再编译 Swift(主程序由本机双架构编译),只用三个冻结脚本产出 arm64 组件,并显式设置 PERFOWL_CORE_PYTHON 指向 venv-py312-arm64。源码提交改为 e10ed16d(与 b236168a 在 Sidecar 与冻结脚本上相同)。Swift 6.1.2 下的编译超时登记为遗留:发版后拆分该视图表达式,使较旧 Xcode 也能从源码构建。
Validation Update · 2026-11-03:公证凭据与试公证
- Owner 提供 App Store Connect API 密钥;以
notarytool store-credentials perfowl-notary --key … --key-id … --issuer …存入本机钥匙串,苹果校验通过。密钥文件、路径与 ID 不进入仓库与日志。 - 用 Intel 单架构候选 build 252(不发布)试公证:首次上传在 S3 加速通道 3 分钟超时(
deadlineExceeded,未进入审核);加--no-s3-acceleration重试,6 分 39 秒返回 Accepted,日志 0 个问题、“Ready for distribution”(E3)。确认全部嵌套二进制带时间戳 + hardened runtime 的签名方式可通过公证;正式发版脚本同样使用--no-s3-acceleration。
执行记录 · 2026-11-03:双架构 1.0.0(build 253)
- arm64 组件:Apple 芯片主机从
d4748af3只运行三个冻结脚本(未编译 Swift),产出草稿 Release 附件 101,245,647 字节,SHA-2568636d86c…238ac;本机下载后 SHA-256 一致,清单 12,893 个文件大小与哈希逐一一致,30 个符号链接均指向包内;对方报告 342 个 Mach-O 全为 arm64,probeready、pymobiledevice3 11.3.1、采集器帮助退出码 0。附件含 macOS tar 自动生成的 15,147 个._*扩展属性文件,解压时排除。对方首次build-sidecar.sh因未设PERFOWL_PYINSTALLER_PYTHON退出 127,设置后成功。 - 组装:main
3451c370(与d4748af3在 Sidecar 与冻结脚本上相同),545 秒;主程序 x86_64 + arm64;647 个嵌套 Mach-O 全部 Developer ID 签名且带时间戳。 - 公证:App 提交
05354a47Accepted 并 stapling;首次打包脚本随后在包内核对失败——核对工具按 Intel 单架构编写,要求每个 Mach-O 含 x86_64;改为Tools/arm64下必须纯 arm64、其余必须含 x86_64 后从断点继续,已 stapling 的 App 未重复公证。DMG 提交0fa41153Accepted 并 stapling。 - 产物:
Perfowl-1.0.0-253-macos-universal-internal.dmg,294,367,964 字节,SHA-256f9663e90c93adf7c7ceb9085884f4ef4223934a274c97fd083cb1999be0f0288。 - 验证(E3,本机 Intel):
codesign --verify --deep --strict通过;spctl结果source=Notarized Developer ID(退出码 0);stapler validate通过;安装后目录树与 DMG 一致;x86_64 冻结核心 109 个模块与源码一致、CLI 一致、probeready;回滚包 251 已校验;启动器唯一。 - 未完成:Apple 芯片 Mac 实测(arm64 组件在本机无法运行)与 Intel Mac 实测(E4)由 Owner 进行;通过后打
v1.0.0标签、发布站点、发送通知。
发版阻断 · 2026-11-03:采集核心启动即崩溃(内部包 246–253)
- 现象:Owner 在 Intel Mac 上用 253 选择设备与应用后,右上角一直显示“正在准备应用采集服务”。本机进程中没有采集核心。
- 复现:按界面同样参数手动运行包内
perfowl_collector_core stream --prewarm,启动即退出:UnboundLocalError: cannot access local variable 'asyncio'(perfowl_collector_core_cli.pymain)。 - 原因:
e6ce454c(2026-11-02,查看文件)在main()的container分支内写了局部import asyncio,Python 因此把整个main()中的asyncio视为局部变量,stream(预热与采集)和screenshot-worker两个命令在到达设备前就崩溃。probe、container、工具箱均不经过该变量,所以包内自检与工具箱测试都没有暴露问题。影响内部包 246–253 的全部性能采集。 - 修复:删除该局部导入(模块顶部已导入)。新增测试
test_main_dispatches_stream_and_screenshot_worker:断言main没有名为asyncio的局部变量,并实际分派stream与screenshot-worker;撤掉修复时该测试失败、修复后通过(E2)。修复后源码对设备 A 预热:hello → provider → device_ready正常(E3)。 - 遗留:采集核心在握手前崩溃时,界面一直停在“准备中”而没有显示失败原因,单独排查。包内核对应增加一次真实的
stream --prewarm冒烟测试(不只probe),防止同类问题再次带进包里。 - 处置:build 253 作废(不发布、不打标签);两种架构都需从修复后的提交重新冻结并重新公证。
Implementation Update · 2026-11-03:标题栏调整(Owner 发版前反馈)
- 去掉标题栏的内部版本号 “Foundation v0.3”。
- 图标与下方左栏卡片左边缘对齐(Owner 选择):系统窗口按钮(红黄绿)单独占顶部 28 点高的一条,品牌与连接状态放在其下 44 点高的一行,左边距 12 点与左栏一致;连接提示横幅相应下移。标题区总高度由 48 点变为 72 点。
- 只改 Swift 界面;Sidecar 与冻结脚本未变,arm64 组件(
31c8ccbc)继续有效。Swift 459 项 0 失败;本地调试版截图核对位置(E3)。
执行记录 · 2026-11-03:双架构 1.0.0(build 254)
- 源码 main
e3ca7780(含采集核心修复与标题栏调整);arm64 组件来自31c8ccbc(Sidecar 与冻结脚本与发版提交相同),草稿 Release 附件 100,765,751 字节,SHA-2568d8daece…cdeac9,本机核对 12,893 个文件一致,无._文件;对方四项检查含stream --prewarm首条输出hello、无 Traceback。build 253 作废。 - 构建 601 秒;主程序 x86_64 + arm64。App 公证
3e804f33Accepted,DMG 公证cb8e40d2Accepted,均已 stapling。 - 产物
Perfowl-1.0.0-254-macos-universal-internal.dmg,288,609,671 字节,SHA-256846eba12dbcc9340fea352a156d7e11a9f75713f58fb2d3e8671342eaaacaa33。 - 本机验证(E3):严格签名、
spctlsource=Notarized Developer ID、stapler validate通过;安装树与 DMG 一致;x86_64 核心 109 模块与源码一致;包内新增冒烟测试stream --prewarm首条hello;回滚包 253;启动器唯一。另用已安装核心对设备 A 走完预热:hello → device_ready → prepare_app_accepted → source_preparation → app_ready(被动观察、不拉起应用,约 2 秒)。 - 待 Owner 在 Intel 与 Apple 芯片 Mac 上实际开始一次性能测试(E4)。
Validation Update · 2026-11-03:真机验收与发布
- Intel Mac(E4):Owner 用 254 完成一次约 4 分钟性能测试(设备 A,iOS 26),会话正常结束、数据完整。整场 FPS 平均 4.56、FTime 平均 5,480 ms 由静止主导:236 秒中 197 秒无新帧,9 个超过 1 秒的静止空档合计 206 秒(最长 60 秒);有帧时逐帧间隔中位 12.5 ms。候选卡顿算法重算:动画 12.4 秒、6 次、5.6 ms/s(candidate,未校准)。登记遗留:报告需标注有效动画时长,避免整场平均误读。
- Apple 芯片 Mac(E4):Owner 确认测试通过。
- 发布:
v1.0.0附注标签指向构建提交e3ca7780,推送 GitHub 与 GitLab;站点下载页与首页标注 1.0.0 内部正式版已发布、不提供公开下载。