feat: integrate performance upgrade and agent inspection tooling
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
# 性能与跨宿主验收 — 2026-09-28 UTC
|
||||
|
||||
本次为本地工作区验收,不代表远程发布、生产容量承诺或所有后端的性能保证。原始测量时间保留在 JSON/XML 中;Windows 本地显示日期可能为 9 月 29 日。
|
||||
|
||||
## 方法与证据边界
|
||||
|
||||
- Windows x64;Unity 2022.3.62f3 的实际 Standalone Player,而非用 EditMode 冒充 Player;另有 .NET 8.0.31、.NET 10 和 Godot 4.6.3 Mono 的实际运行。
|
||||
- 网络矩阵:64 B/1 KB/32 KB 负载参数,1/32/256 会话;RPC、广播、慢消费者、突发队列。Loopback 会话不是 OS socket;TCP 文件是实际本机 socket,且 RPC 采用串行往返采样,不等于高并发容量压测。
|
||||
- Context:10/100/1000 组件依赖链,10,000 次创建退役;旧实现来自 Context 子模块提交 b93f3e61223e7572588b67c0d3935073817f0da6,不是重新编写的假想基线。
|
||||
- 存档:100 KB/1 MB/10 MB,前台/后台编码;.NET 每组合 10 次并覆盖加密,Player 记录真实阶段耗时与采集线程。输入主要为字符串快照,不能推断复杂游戏对象的采集成本。
|
||||
- 单机开发环境、有限样本,非隔离实验机;p99 易受 JIT、GC、系统调度影响。没有可靠的多轮置信区间,不将小幅波动称为普遍提升。
|
||||
- Unity 的 GC.GetAllocatedBytesForCurrentThread 对已知分配返回零,已弃用该结果。Player 改用经已知数组分配校准的 GC.Alloc 事件计数;事件次数不是 B/op。独立 .NET 的字节计数与 Player 分开报告。
|
||||
|
||||
原始数据位于 [Data/2026-09-28](Data/2026-09-28/);Player 完整输出同时保存在 XML 与 player-output.txt。工具、测试源代码保留在 Tools/AgentSupport 与 Assets/AgentSupportTests。
|
||||
|
||||
## 已量化的核心变化
|
||||
|
||||
### Context(.NET 8)
|
||||
|
||||
| 组件数 | 旧诊断 p95 µs | 新诊断 p95 µs | 旧 B/op | 新 B/op |
|
||||
|---:|---:|---:|---:|---:|
|
||||
| 10 | 9.4 | 11.7 | 10,456 | 7,312 |
|
||||
| 100 | 538.2 | 116.9 | 108,016 | 73,456 |
|
||||
| 1000 | 7,426.4 | 548.3 | 1,083,616 | 735,328 |
|
||||
|
||||
大规模诊断通过按依赖键访问 provider 候选索引获益;10 个组件的 p95 本轮反而略高,不能宣称所有规模都更快。10,000 次退役后旧运行时持有 10,000 个 fiber,新运行时为 0,诊断历史有界 64。弱引用测试验证实例可回收;整进程 GC 差值可能为负,不将其解读为精确节省字节数。
|
||||
|
||||
深链生命周期改为迭代队列展开,避免 1000 层同步完成/撤回造成栈溢出;不改变依赖排空与效应撤回顺序。
|
||||
|
||||
### 网络封装(.NET 8)
|
||||
|
||||
| 负载参数 | 旧 JSON 外封装 B/op | 新 v2 外封装 B/op |
|
||||
|---:|---:|---:|
|
||||
| 64 B | 3,504 | 32 |
|
||||
| 1 KB | 10,560 | 32 |
|
||||
| 32 KB | 230,328 | 32 |
|
||||
|
||||
这里只比较已经编码的消息体如何封装,不是端到端零分配。新封装取消外层 JSON/Base64,消息直接写入池化 buffer;仍有 writer 对象、消息反序列化、排队和 transport 的独立成本。JSON 与生成式 MessagePack 的完整消息编码对照见原始 rows,不能套用此表的 32 B。
|
||||
|
||||
队列突发测试输入 10,000 个显式可替换状态,32 个 session 分区最终保留 32 项、32 KB,返回 9,968 次 Replaced;一次 4 KB budget 泵送完成 4 项。可靠操作不使用这种替换机制,满队列显式拒绝。
|
||||
|
||||
### 实际 TCP 与后端选择
|
||||
|
||||
256 个本机 TCP 连接、1 KB、256 次串行 RPC 往返:
|
||||
|
||||
| 运行时 | p50 µs | p95 µs | p99 µs | ops/s |
|
||||
|---|---:|---:|---:|---:|
|
||||
| .NET 8 | 99.3 | 258.9 | 355.1 | 6,911 |
|
||||
| .NET 10 | 88.4 | 250.8 | 384.3 | 7,392 |
|
||||
|
||||
其他参数组合有升有降;本轮未证明目标场景稳定达到 15% 收益,因此不引入新的默认 .NET 10 专属服务端依赖。Pipelines 仅有内存 buffer roundtrip 微实验,未实现等价 socket 后端对照,不足以采纳。共享运行时继续 netstandard2.1。
|
||||
|
||||
TCP 慢消费者测试证明有界队列和拒绝反馈,不证明业务消费成功:该突发负载使用 RPC 消息的一次性发送路径,记录中存在 DispatchMissCount;不能将该行视为完整 handler 吞吐测试。可靠队列行为、会话隔离、取消和故障另由功能测试验证。KCP 未作独立吞吐结论。
|
||||
|
||||
### EventBus 与存档
|
||||
|
||||
.NET 8 同步 Post、同步完成的异步 Post 为 0 B/op;注册/撤回 224 B/op,按需绑定诊断 120 B/op。同步路径的捕获闭包已移出快路径;Unity 的结构体事件空值检查另外增加值类型短路,避免 Mono 装箱。
|
||||
|
||||
校准后的 Player 实测:独立 Bus 10,000 次同步发布为 0 次分配事件;当前默认 Bus 为 10,000 次分配事件。修复值类型空值检查前默认通道是 20,000 次,不能将早先字节 API 的零值作为基线。
|
||||
|
||||
默认全局 Bus 可能带网络桥或诊断观察器;接口观察器需要结构体装箱,不能把独立 Bus 的零分配结果扩大到所有配置。Player 同时测量默认与独立通道,并为引用类型空值保留异常检查。
|
||||
|
||||
存档采集仍在调用线程,后台开关仅移动脱离宿主对象的快照编码与加密。示例 .NET 8 的 10 MB 未加密平均编码为前台约 7.68 ms、后台约 8.21 ms;主要收益是主线程工作转移,而非宣称总保存时间必然缩短。Player 的冷启动与各阶段实测见 player-output.txt;未隐藏首轮高耗时。格式、原子落盘、取消时备份保留及损坏回退均有测试。
|
||||
|
||||
## 复现
|
||||
|
||||
在已还原依赖的仓库运行:
|
||||
|
||||
~~~powershell
|
||||
pwsh Tools/AgentSupport/Benchmarks/Prepare-Baseline.ps1
|
||||
dotnet run --project Tools/AgentSupport/Benchmarks -c Release -f net8.0 -- Artifacts/AgentSupport/benchmark-net8.json
|
||||
dotnet run --project Tools/AgentSupport/Benchmarks -c Release -f net10.0 -- Artifacts/AgentSupport/benchmark-net10.json
|
||||
dotnet run --project Tools/AgentSupport/Benchmarks -c Release -f net8.0 -- --tcp Artifacts/AgentSupport/tcp-net8.json
|
||||
dotnet test Tools/AgentSupport/RuntimeTests
|
||||
dotnet test Tools/AgentSupport/Shrink.Inspect.Tests
|
||||
~~~
|
||||
|
||||
Unity 用 TestRunner 的 StandaloneWindows64 Player 运行 ShrinkSDK.AgentSupport.PlayerTests;Editor 辅助入口 PlayerAcceptance.Run() 将本次结果保存到 Artifacts/AgentSupport/unity-player-results.xml。基线脚本读取子模块 HEAD:以后 HEAD 前进时,应显式使用上述旧提交重建对照,不把新的 HEAD 当成本报告基线。
|
||||
|
||||
最终功能验收、消费工程已知失败和导航覆盖范围见 [AgentSupportAcceptance](../AgentSupportAcceptance.md);协议和回退见 [迁移说明](../NetworkV2Migration.md)。
|
||||
Reference in New Issue
Block a user