You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
AdLike2048/docs/性能分析-抖音线上发热卡顿崩溃.md

11 KiB

性能分析:抖音小游戏线上发热 / 卡顿 / 崩溃

日期:2026-09-17
范围:静态代码 + 资源 + 构建配置审计(无线上 PF 原始日志、无真机 Profiler)
渠道:sdkConfig.config.chanId = tt(DefaultConfig / 悟空别走)
方法:全平台内存方案七大支柱 × 全面性能工程五维(加载 / 内存 / FPS / CPU / 发热)

一句话:中后期双口叠波没有同屏上限,战斗又全程 60fps 并用固定步长追赶表现同步,再叠加进战资源峰值与退战保留战斗包,低中端抖音机会同时出现发热、掉帧、OOM 杀进程。


1. 观测结论(当前能确定什么)

本次没有线上 PF-MEM-WARN / PF-THRM-FPS 原始样本,不能把「人均告警次数」写成数字。能确定的是机制本身足以在真机上同时打出三类症状:

症状 主因类型 峰值还是基线
崩溃(杀进程 / 白屏 / 闪退) GPU 纹理 + JS 节点/Spine 峰值;同屏怪无上限 峰值为主,长局再叠 基线
卡顿 固定步长追赶 × 全量 onCombatTick;2 倍速再乘 战斗中持续,掉帧后恶化
发热 战斗 60fps 不降、iOS 高性能模式、常亮、Box2D、Spine 战斗相位持续

建议立刻用现有打点核对(见 docs/性能打点说明.md):

  • PF-BOOT-TIER:抖音大盘 m* / q* 分布(大量 7.3–8.5 分会落 medium / tier1)
  • PF-MEM-WARN:是否集中 ph3(战斗)
  • PF-SESS-END:退战后 b/p/a/r 是否回落
  • PF-THRM-FPS:战斗是否几乎全是 fps60

2. 阶段图与峰值叠加点

Boot 最小包 (first/comm/home + BootRes)
  │  kickLoad 战斗五包 zip(不可 abort)
  ▼
Hall 可交互
  │  kickAllRemainingBundleZips + silent 大厅 UI
  │  匹配页 scheduleBattleWarm → loadResPakg(BattleRes)
  ▼
进战  ★峰值1
  │  大厅包未卸干净 + 战斗 zip 解压 + loadResPakg + 关面板
  │  PhysicsSystem2D.enable = true
  ▼
COMBAT  ★峰值2(随波次单调变差)
  │  双口出怪、波次重叠、无 maxConcurrent
  │  60fps + 30Hz 逻辑最多追 5 步/渲染帧
  │  startBattleSilentDownload(popBattle / loadDir)
  ▼
退战
  │  tier1/3:battleRetain 钉住五包 zip,大厅仍扛战斗包  ★基线抬升
  ▼
下一局进战  ★峰值3(大厅 + 保留战斗包 + 新 load)

3. 七大因素对照

因素 现状 对策 平台影响
纹理/Spine/音频 52 张 max 边 >1024;剑/棍/枪合图近 2k;地图背景 1100×1667;构建有 ASTC 8×8,Spine/背景未挂 per-asset 压缩 拆武器 atlas、压背景、真机确认 GFX 格式 抖音低内存机 GPU OOM
加载/预载 Boot 即并行 kickLoad 战斗包;开战后再 startBattleSilentDownload 战斗 COMBAT 禁 silent;kickLoad 错峰到点击开始 进战瞬间 IO+解压发热
释放/生命周期 退战顺序正确;tier1/3 enableBattleResRetain=true;战斗中告警不能卸 retain 抖音默认关 retain,直到有 B/P/A 证据 大厅基线高,二次进战峰值
引擎引用/UI 关面板 destroy 成对;节点池 无上限 池加 cap,长局 trim 长局 JS+节点膨胀
JS 堆 热路径 sort / new 数组;world.gc 每 60 逻辑帧全扫 表现同步降频;有界 cache 掉帧后 GC 尖峰
逻辑/表现热路径 见 §4,P0 表现 1 次/渲染帧;同屏 cap 发热+卡顿主因
平台/容器 iOS High Performance Mode Plus 打开;战斗 setKeepScreenOn(true);deviceScore≥7.30 当中端 iOS 高性能仅高档;中端按低内存策略 抖音 iOS 发热、Android 杀后台

4. P0 根因(必须先做)

4.1 双口叠波 + 无同屏上限(崩溃 / 卡顿 / 发热共同主因)

项 证据
配表 Level.json 第 18–25 波每波 50 只,间隔 1.6s
双口 LevelWaveParser.toWaveDefs 每波 port1(攻 AI)+ port2(攻玩家)各一份 → 100 只/波
叠波 BattleRuntime 创建会话 waveClearRequiresKillAll: false;Const 10 = 1,8(后续波 8 秒就开下一波)
上限 WaveSpawner._canSpawnMore:maxConcurrent 缺省 0 = 不限;Level 表无该字段

一波 50 只 × 1.6s ≈ 80s 才出完;8s 开下一波。清不掉时理论上可叠约 10 波 × 100 ≈ 1000 只同屏(杀怪会压下来,但中后期 2 倍速仍可到百级)。每只怪带 Spine + 运动同步 + Kinematic RigidBody2D。

根因:对抗玩法把出怪乘 2,又允许波次重叠,却没有按档位的同屏硬顶。

4.2 固定步长追赶把表现同步乘最多 5 倍(卡顿正反馈 / 发热)

  • 逻辑 fixedStep = 1/30,maxFixedIterations = 5(BattleSession)
  • 每一步 COMBAT 都调 CocosBattleMovementBridge.onCombatTick:遍历全部怪物节点 syncMonsterNode + 全阴影 + Spine LOD
  • 掉到 20fps 时,一帧最多跑 5 次逻辑 + 5 次全量表现同步 → 更掉帧 → 更追赶

tickSliceCount 只切 ECS system,不切 bridge。2 倍速 TimeScale=2 再把追赶窗口加宽。

根因:表现桥接绑在 _tickOnce 上,而不是「每渲染帧 1 次」。

4.3 战斗相位强制 60fps,温控故意不降帧(发热)

thermal-profile.json.ts 三档都是 battleFrameRate: 60,且:

  • enablePhaseFrameRate: false
  • enableStressFrameRate: false

ThermalGovernor 注释写明:禁止用降帧换发热。内存告警只停 silent。抖音中端(deviceScore 7.30–8.50)仍满帧 + 飘字 24 + 受击 16 + 关 Spine LOD 间隔 30。

叠加:

  • build-templates/bytedance-mini-game/game.json:enableIOSHighPerformanceMode + Plus 均为 true
  • 战斗 AppLifecycle.setBattleKeepScreen(true) → 无法靠熄屏降温

根因:流畅策略覆盖了低中端机的热预算;iOS 高性能模式把 GPU 顶满。

4.4 进战 / 退战内存峰值(崩溃)

叠加 位置
Boot 完成后并行 kickLoad 战斗分包(不可 abort) BootPipeline → PreloadPredictor.startEarlyBattleBundleDownload
开战后再 startBattleSilentDownload GameController 打开 BattleGame 成功后
中端/高端退战 enableBattleResRetain=true 钉五包 zip memory-profile.json.ts tier1/3;GameController._enterMainReleaseBattleAndLoadHall
战斗中 onMemoryWarning 不能卸 retain MemoryDowngrade._releaseRetainedBattleRes:phase===Battle 直接 return
节点池无 cap ResourcesManager.putNode

抖音 ≥7.30 分 = medium = tier1 = 开 retain。这是抖音大盘主力机,不是「高端才开」。


5. P1(放大 P0,或单独造成中度问题)

ID 问题 位置 贡献
P1-1 DeviceProfile.monsterSortInterval 未接线,Y 排序仍事件触发全量 DeviceProfile vs CocosBattleMonsterPresenter.sortMonstersByY CPU
P1-2 主线固定 mode: 'pvp',双玩家槽 + AiBattleBridge 每帧 tick GameController / UIBattleGame.update CPU/内存近翻倍
P1-3 BattleRuntime.tick 串行十余个 Host(雷公/哪吒/箭雨/长矛/被动/弓/AI…) BattleRuntime.ts 783+ CPU
P1-4 每怪 Kinematic RigidBody2D,进战开 PhysicsSystem2D Monster.ts / BattlePhysicsGate CPU/发热
P1-5 武器皮肤+技能 多皮肤一张 atlas(剑 1961、约 3.18MB 源图) assets/res/battleGameWeapon/spine/like/... GPU
P1-6 地图/大厅全屏背景 1100×1667,超 Tier-0 单图 1024 花果山背景.png 等 GPU
P1-7 MemoryProfile.reapplyAfterProbe 全仓库无调用;DeviceProfile._tier 首次访问后锁死 MemoryProfile.ts / DeviceProfile.ts 档位可能偏乐观
P1-8 TargetResolver 威胁排序比较里反复 estimatePathLength(含 sqrt) TargetResolver.ts CPU 尖峰
P1-9 enableConsolePfLog = true(Release 虽 noop console.log,开发包/部分宿主仍有 I/O) sdkConfig.ts 次要

6. 五维影响(若不改)

加载 内存 FPS CPU 发热
首局被战斗 zip 并行下载托住 进战峰值 = 大厅+战斗+silent;tier1 退战基线不回落 掉帧后追赶使帧时更长 同屏实体 × 追赶次数 × Host 链 60fps + iOS Plus + 常亮 + Box2D

7. 建议治理顺序(策划数值不变)

不改出怪数量、间隔、奖励。只加表现/内存硬顶与生命周期。

立刻(P0,可分 PR)

  1. 同屏硬顶:按 DeviceCapability.quality 设默认 maxConcurrent(建议 low 40 / medium 60 / high 80,含双口合计)。超限只推迟出怪,不改配表只数。
  2. 表现同步每渲染帧最多 1 次:固定步长多步时仅最后一步调 onCombatTick;阴影/LOD 再降频。
  3. 抖音默认关 enableBattleResRetain(或仅 high + 未收到过 MEM-WARN)。战斗相位告警允许 releaseOwner('battleRetain')。
  4. COMBAT 停止 startBattleSilentDownload;Boot kickLoad 战斗包改为「点开始后」或更低并发。
  5. iOS:enableIOSHighPerformanceModePlus 仅高档或关掉 Plus;验证发热。

随后(P1)

  1. low/medium 战斗目标帧 45(内存 D2 再 30);大厅可保持 60。这与当前「战斗不降帧」产品策略冲突,需要明确授权。
  2. 接上 monsterSortInterval;AI 决策降频。
  3. 节点池 cap + 长局 trim。
  4. 拆武器合图、压 1667 背景、Spine/背景挂压缩预设。
  5. 评估战斗是否必须每怪刚体(逻辑命中已存在则关物理)。

回归(Release + 抖音真机,不可用编辑器代替)

  • 清缓存冷启动 → 立刻开战 / 大厅停 10s 再战
  • 战斗 ↔ 大厅 ×10:无缺图、B/P/A 不单调涨
  • 打到第 18 波以后:同屏怪数、帧时、tt.onMemoryWarning
  • 2 倍速 15 分钟:发热主观 + 是否杀进程
  • 机型:deviceScore <7.3、7.3–8.5、≥8.51 各至少 1 台;iOS 开/关高性能模式对比
  • 弱网进战、切后台 5s

8. 未决(需策划 / 发行 / 真机)

  • 同屏 cap 是否允许「推迟出怪」改变手感(数量不变,节奏变)
  • 战斗降到 45fps 是否可接受
  • 线上 PF-MEM-WARN 是否集中 ph3、是否与 retain 机型重合
  • 抖音包实际 ASTC 上传率(开发者工具会强制 PNG,不能当证据)

9. 相关代码入口

模块 路径
波次双口 assets/script/battle/config/LevelWaveParser.ts
无并发上限 assets/mx/module/battle/unit/WaveSpawner.ts
固定步长 + bridge assets/mx/module/battle/core/BattleSession.ts、CocosBattleMovementBridge.ts
60fps 策略 assets/script/game/thermal-profile.json.ts、ThermalGovernor.ts
内存档 / retain assets/script/game/memory-profile.json.ts、GameController.ts
抖音分档 assets/script/game/device-capability-standards.ts
降档不卸战斗 assets/script/game/MemoryDowngrade.ts
iOS 高性能 build-templates/bytedance-mini-game/game.json