[P1][CR-F6/F7] 渲染热路径每帧分配与 DOM 布局抖动 #531
Loading…
Reference in New Issue
No description provided.
Delete Branch "%!s(<nil>)"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
问题描述
渲染热路径每帧都会分配大量临时对象和闭包,HUD 和头顶标签每帧读写 DOM 布局属性。实体、标签数量一多,GC 停顿和强制同步布局(layout thrashing)就会造成掉帧。
说明:本次评审没有做运行时 profiling,以下结论全部来自代码层面的分配和 DOM 读写分析。修复前请先测量(见"修复指南"第 1 步),按实测数据排优先级。
证据
F6:每帧分配
onTick/onRender(act-scene.ts:571-646):onRender每帧构造一个约 40 个字段的上下文对象;onTick每个 tick 构造一个约 15 个字段的对象,还会调用一次document.querySelector('#dialog')(L597)。renderWorldLayers(world-renderer.ts:533)每帧都会:{ atlas },为每个阴影新建{ atlas, tint };{ x, y, depth, draw }和一个draw闭包,再对整个数组排序;.filter().map(),生成 automap 数据。getActiveButtons(frontend-renderer.ts:561,约 436 行):每次渲染、每个鼠标事件都会重建整张按钮表和其中的闭包。F7:布局抖动
HudManager.render每帧先读clientWidth/clientHeight(hud-manager.ts:1277-1278),再写 style(L1297)。clientToLogical读getBoundingClientRect()(hud-manager.ts:657-659),再写style.pointerEvents(hud-manager.ts:860)。updateOverheadLabels每次调用都读一次getBoundingClientRect()(overhead-labels.ts:240),然后给每个标签写约 10 个 style 属性(overhead-labels.ts:304-313)。其中 color、background、border、padding、borderRadius、fontWeight、boxShadow 这 7 个是常量,每帧都在重复写。根因
修复指南
onTick/onRender的上下文对象在SceneController(见 #526)里只创建一次,每帧只更新会变的字段;#dialog元素在初始化时查找一次,缓存起来。{ atlas }、{ atlas, tint }按 atlas 缓存,或者改为向renderer.draw传入原始参数;draw闭包改为"实体类型 + 索引",由一个固定的分发函数来画;getActiveButtons以"当前界面状态"为 key 缓存,状态变化时才重建。ResizeObserver缓存(再加上 scroll / resize 事件更新位置),热路径里不再调用getBoundingClientRect;transform: translate(...)代替left/top;验收标准
renderWorldLayers在实体数量不变时,每帧不再为每个 tile / 实体分配新对象。updateOverheadLabels和 HUD 的 mousemove 中不再调用getBoundingClientRect。npm run typecheck0 error;npx vitest run全部通过。相关
SceneController。renderWorldLayers的拆分。