性能基准:Client 和 Server 不是报告里的两个标签

自动关联目录:性能基准:Client 和 Server 不是报告里的两个标签

核心判断:把同一段循环分别标成 Client 和 Server,只能验证统计器,不能证明两个运行目标的性能。可信基准必须真正经过目标的调度、脚本、对象、网络与生命周期路径。

一、业务冲突:需要回归门禁,但微基准很容易测错对象

高频脚本更新或能力调度一旦退化,会同时影响本地客户端和 DS。建立自动基准、预热、采样 P50/P95/P99、输出机器与构建信息,方向完全正确。但如果基准为了稳定而绕过真实调度器,它测到的可能只是一个 C++ 循环,而不是系统成本。

二、实际实现:统计框架完整,工作负载替身过轻

现有基准区分“没有更新函数”“空更新”“典型向量与属性计算”,先预热再采样,输出并发量、派发数、分位数和单次中位耗时,并为 Client/Server 各生成一组结果。它还写出 CPU 和 Build Configuration,具备机器可读报告。

但 Client 和 Server 只是外层字符串;两者执行同一个容器和同一个 Lambda,没有创建不同 NetMode/World/VM,也没有经过真实活跃集、脚本调用、跨语言栈、对象查找和生命周期过滤。“无更新函数”用直接返回零模拟,因此无法发现真实调度器误扫描全部非活跃实例的回归。

三、值得保留:一个好的 Harness 已经成形

  • 预热与正式采样分开,减少一次性初始化干扰。
  • 分位数和派发数量同时断言,避免通过少做工作获得更快结果。
  • 无更新、空更新和典型更新区分了扫描、调用与业务体成本。
  • 报告携带机器和构建配置,为后续基线分组留出接口。

四、结构性缺陷:绝对阈值与角色标签都缺少执行语义

硬编码毫秒阈值会受 CPU、后台负载、构建优化级别和计时噪声影响。仅把这些环境写入报告,不代表门禁会按环境选择正确基线。更重要的是,替身逻辑没有触发 UObject/GC、脚本 VM、队列、网络相关性和 DS 权威分支,优化替身不一定改善真实帧。

微基准仍有价值,但它只能回答局部算法问题,例如“密集活跃数组是否比扫描全表更快”。它不能单独回答“DS 同时运行大量能力时能否守住帧预算”。

五、目标设计:三层基准,不让一层冒充另一层

层级测什么必须经过
Micro容器、评分、序列化等纯算法真实函数,固定输入
Component调度器/VM/对象桥接真实活跃集、取消、代次、空回调
ScenarioClient/DS 端到端真实 Target、World、玩家、网络、生命周期
for (Target target : {Client, DedicatedServer}) {
    Process p = LaunchCookedTarget(target, fixture);
    p.WaitForWarmupMilestone();
    p.RunScenario(workloadId, duration);
    Report r = p.CollectTraceAndCounters();
    AssertPerformance(r, BaselineKey(target, deviceClass, build));
    AssertGameplayInvariants(r);
}

Scenario 使用同一个 SessionId 串联启动、DS Ready、Client Join、Playable 和稳态窗口。Client 记录 Game/Render/GPU、输入到呈现延迟与资源提交;DS 记录 GameThread、AI/脚本/物理/复制阶段、连接数和权威结果。二者共享工作负载描述,不共享错误的指标集合。

六、门禁策略:看变化,也守绝对体验

同机同配置用相对基线检测回归,设备档位用绝对预算守体验。建议同时满足:

ΔP95=P95new−P95baseP95base≤r\Delta P95=\frac{P95_{new}-P95_{base}}{P95_{base}}\le r

以及 P99 <= TargetBudget、派发数正确、无积压增长、玩法结果一致。合成示例:微基准快 15%,真实 DS Scenario 却因对象查找增加而慢 8%,应以 Scenario 阻断合入;数字仅说明判定方式。

最终决策规则:角色名称必须对应真实执行环境;微基准定位原因,组件基准验证机制,端到端场景才有资格承担发布门禁。