5cd92254e1
- What: 新增 `scene3d/protect.py`(封套 v2:Ed25519 签名 + 可选 AES-256-GCM,nonce/salt 每包唯一、 元数据作 AAD、明文摘要进签名、KeyProvider 只问 get_content_key)与 `record/visualization3d.py` (session.json 的 visualization3d 块:写入版本化、读取时缺块=不支持);`package.py` 支持 v2 (payload=plain 仅签名 / aes-gcm 签名+加密)并继续读 v1,新增解压比上限与"写入后自读回"校验; `contracts.py` 新增 PlatformLock/PlatformInfo/check_platform_lock、Sealing、platform_mismatch 诊断码; `Scene3DView` 在装配前查 OS/架构、拿到 capabilities 后查图形半区,违反即撤下场景并在面板显示原因; 工具 `compile_scene.py` 新增 --sign-key/--write-verify-key/--encrypt-key-id/--key-file/--lock-from-probe, `validate_scene.py` 新增 --key-file/--key-id/--verify-key/--require-signature(发布门禁), 新增 `bench_scene.py`(p50/p95 分阶段 + --cpu-only + --vertices N + --package)与 `soak_scene.py`(RSS 四分位速率 + 队列上界 + 抽稀采样);两份报告落到 docs/architecture/。 - Why: 规格 §5.2 的保护目标是"提高复制成本"而不是"防提取",所以要的是签名(来源)+ 可选认证加密(机密性) + 密钥隔离,而不是自制加密或把 ZIP 当加密;§12 的"包保护/性能/长时"三行需要可复现的数字与判定标准, 而不是一次性的观感。平台锁定还必须只降级三维:锁定不通过时二维照常。 - Verification: shared 全量通过(新增 test_scene3d_protect.py 35 项:封套往返/篡改/密钥/锁定/记录块/ compile→validate 端到端发布流程;test_scene3d_package.py 20 项含 v1↔v2 兼容);apps/studio 全量通过 (test_scene3d_view.py 30 项含锁定拒绝与 session.json 块);ui_check 566 项 0 失败;locale_check 0 缺失; 真实资产端到端:1032 顶点编译出 signed+sealed+locked 包(56 927 B 密文),validate --require-signature 退出 0, 改一个字节退出 2;性能报告(perf-report-windows-dev.json):1032 顶点 compose p50 0.50 ms(30 fps 上限内), 20022 顶点/39480 三角形 compose p50 6.15 ms(约 33 ms 帧的 18%),采集线程 submit p95 < 0.4 ms(合成器被人为放慢到 50 ms); 长时报告(soak-report-windows-dev.json):无窗口 10 min/60 fps 尾段 0.354 MB/min,GUI 4 min/30 fps 尾段 0.809 MB/min, 队列上界(mailbox=1、单飞行合成)两者均成立。过程中修掉:GUI 进程里的合成器计时被 GIL/vsync 污染(98.8 ms vs 真值 6.1 ms)、 跨线程读 last_stats 撕裂、key id 无 provider 时会静默写明文包、soak 工具自身记时间列表会无界增长、RSS 读取失败伪装成零增长、 平台锁定不是终态诊断。 - Not in this change: ARM 板卡的能力报告与 2 小时门禁运行(按用户要求暂缓;命令与判定标准已写入阶段 5 文档); GPU 显存随时间的测量(无可移植 API,报告说明渲染器缓冲估计恒定且更新路径不新建 GPU 对象); `cryptography` 在此环境无法联网安装,本机验收用的是本机已有的 cp310 构建(pyproject 里已声明为可选 extra `protected-assets`)。
463 lines
14 KiB
JSON
463 lines
14 KiB
JSON
{
|
|
"kind": "orisys-scene-perf-report",
|
|
"version": 1,
|
|
"stage": "docs/architecture/studio-3d-stages.md 阶段 5(性能与长时)",
|
|
"host": {
|
|
"os": "Windows 10",
|
|
"os_family": "windows",
|
|
"machine": "amd64",
|
|
"python": "3.10.19",
|
|
"cpu": "AMD64 Family 26 Model 68 Stepping 0, AuthenticAMD",
|
|
"note": "developer workstation; the ARM boards are the second platform and have not been probed yet (user asked to defer ARM work)"
|
|
},
|
|
"method": {
|
|
"tools": "tools/scene_assets/bench_scene.py",
|
|
"gui_mode": "assembled Scene3DView (widget + camera + renderer + composer + coordinator) in a real window; frames are submitted through the same submit_packet() the acquisition thread calls, ticked and painted",
|
|
"cpu_mode": "--cpu-only: the same composer with no window in the process",
|
|
"percentiles": "p50/p95 of the per-frame measurements; latency is submit-to-paint and therefore includes the frame-rate limiter",
|
|
"compose_split": "compose_sample and compose_normals are the composer's own timers for the two halves of the work",
|
|
"why_two_modes": "In the GUI run the worker thread competes with the GUI thread for the GIL and for a vsync-throttled swap, so the composer's wall-clock timers pick up waiting that is not arithmetic: the same 20k-vertex scene reports compose p50 98.8 ms in the GUI run and 6.1 ms with --cpu-only. Per-frame CPU cost is therefore quoted from --cpu-only; upload, paint and latency are GUI-thread measurements and are unaffected.",
|
|
"artificial_delay": "the submit budget is measured with a deliberate 50 ms composer delay, because that is the case where a display could damage the acquisition loop if the mailbox were wrong"
|
|
},
|
|
"budget_from_design_document": {
|
|
"sensing_surface": "about 20k vertices / 40k triangles",
|
|
"housing": "about 10k-20k triangles",
|
|
"display_rate": "30 fps suggested; 15 fps allowed on a low-end board, acquisition and recording rates must not drop",
|
|
"dynamic_bytes_per_frame": "about 0.64 MB at 20k vertices (position/normal/scalar/valid, 32 bytes)"
|
|
},
|
|
"runs": {
|
|
"poc_gui": {
|
|
"profile_requested": "desktop33",
|
|
"frames_requested": 400,
|
|
"viewport_px": [
|
|
900,
|
|
700
|
|
],
|
|
"slow_compose_ms": 50.0,
|
|
"max_fps_requested": 30,
|
|
"context": {
|
|
"profile_used": "desktop33",
|
|
"vendor": "NVIDIA Corporation",
|
|
"renderer": "NVIDIA GeForce RTX 4080 SUPER/PCIe/SSE2",
|
|
"gl_version": "3.3.0 NVIDIA 610.88",
|
|
"glsl_version": "3.30 NVIDIA via Cg compiler",
|
|
"software_renderer": false,
|
|
"max_texture_size": 32768,
|
|
"device_pixel_ratio": 1.0,
|
|
"qt_platform": "windows"
|
|
},
|
|
"mesh": {
|
|
"sensing_vertices": 9,
|
|
"sensing_triangles": 8,
|
|
"housing_triangles": 12,
|
|
"field_domain_hw": [
|
|
3,
|
|
3
|
|
],
|
|
"estimated_gpu_bytes": 2096
|
|
},
|
|
"timings_ms": {
|
|
"submit": {
|
|
"p50": 0.0662,
|
|
"p95": 0.1042,
|
|
"max": 0.2491,
|
|
"mean": 0.0678,
|
|
"n": 400
|
|
},
|
|
"compose": {
|
|
"p50": 0.284,
|
|
"p95": 16.0868,
|
|
"max": 16.9735,
|
|
"mean": 5.4679,
|
|
"n": 400
|
|
},
|
|
"upload": {
|
|
"p50": 0.1716,
|
|
"p95": 0.3097,
|
|
"max": 0.3499,
|
|
"mean": 0.1821,
|
|
"n": 400
|
|
},
|
|
"paint": {
|
|
"p50": 0.6612,
|
|
"p95": 0.9826,
|
|
"max": 22.5669,
|
|
"mean": 0.7215,
|
|
"n": 401
|
|
},
|
|
"latency": {
|
|
"p50": 83.3294,
|
|
"p95": 100.2022,
|
|
"max": 101.038,
|
|
"mean": 86.367,
|
|
"n": 95
|
|
}
|
|
},
|
|
"display": {
|
|
"superseded_display_frames": 304,
|
|
"stale_frames": 0,
|
|
"invalid_frames": 0,
|
|
"max_inflight_composes": 1,
|
|
"mailbox_capacity": 1,
|
|
"frames_presented": 94
|
|
},
|
|
"crypto_backend": "49.0.0",
|
|
"verdict": "ok",
|
|
"exit_code": 0
|
|
},
|
|
"poc_cpu": {
|
|
"mode": "cpu",
|
|
"frames_requested": 500,
|
|
"scene": "synthetic-poc",
|
|
"mesh": {
|
|
"sensing_vertices": 9,
|
|
"sensing_triangles": 8,
|
|
"field_domain_hw": [
|
|
3,
|
|
3
|
|
]
|
|
},
|
|
"timings_ms": {
|
|
"compose": {
|
|
"p50": 0.047,
|
|
"p95": 0.0488,
|
|
"max": 0.0809,
|
|
"mean": 0.0473,
|
|
"n": 500
|
|
},
|
|
"compose_sample": {
|
|
"p50": 0.0129,
|
|
"p95": 0.0132,
|
|
"max": 0.0395,
|
|
"mean": 0.013,
|
|
"n": 500
|
|
},
|
|
"compose_normals": {
|
|
"p50": 0.0256,
|
|
"p95": 0.0265,
|
|
"max": 0.0448,
|
|
"mean": 0.0257,
|
|
"n": 500
|
|
},
|
|
"compose_wall": {
|
|
"p50": 0.0475,
|
|
"p95": 0.0494,
|
|
"max": 0.0816,
|
|
"mean": 0.0479,
|
|
"n": 500
|
|
}
|
|
},
|
|
"verdict": "ok",
|
|
"exit_code": 0
|
|
},
|
|
"real_asset_gui": {
|
|
"profile_requested": "desktop33",
|
|
"frames_requested": 300,
|
|
"viewport_px": [
|
|
900,
|
|
700
|
|
],
|
|
"slow_compose_ms": 0.0,
|
|
"max_fps_requested": 30,
|
|
"scene": "package:D:\\orisys_ws\\.repro\\build\\finger-display-1.0.0.oryscene",
|
|
"context": {
|
|
"profile_used": "desktop33",
|
|
"vendor": "NVIDIA Corporation",
|
|
"renderer": "NVIDIA GeForce RTX 4080 SUPER/PCIe/SSE2",
|
|
"gl_version": "3.3.0 NVIDIA 610.88",
|
|
"glsl_version": "3.30 NVIDIA via Cg compiler",
|
|
"software_renderer": false,
|
|
"max_texture_size": 32768,
|
|
"device_pixel_ratio": 1.0,
|
|
"qt_platform": "windows"
|
|
},
|
|
"mesh": {
|
|
"sensing_vertices": 1032,
|
|
"sensing_triangles": 1974,
|
|
"housing_triangles": 0,
|
|
"field_domain_hw": [
|
|
300,
|
|
280
|
|
],
|
|
"estimated_gpu_bytes": 90760
|
|
},
|
|
"timings_ms": {
|
|
"submit": {
|
|
"p50": 0.1666,
|
|
"p95": 0.2838,
|
|
"max": 0.4235,
|
|
"mean": 0.1796,
|
|
"n": 300
|
|
},
|
|
"compose": {
|
|
"p50": 16.0998,
|
|
"p95": 16.7335,
|
|
"max": 32.012,
|
|
"mean": 15.5992,
|
|
"n": 299
|
|
},
|
|
"compose_sample": {
|
|
"p50": 0.6744,
|
|
"p95": 15.6332,
|
|
"max": 17.8982,
|
|
"mean": 7.4582,
|
|
"n": 299
|
|
},
|
|
"compose_normals": {
|
|
"p50": 0.7236,
|
|
"p95": 1.2651,
|
|
"max": 16.4823,
|
|
"mean": 1.4222,
|
|
"n": 299
|
|
},
|
|
"compose_wall": {
|
|
"p50": 16.1051,
|
|
"p95": 16.7427,
|
|
"max": 32.0177,
|
|
"mean": 15.6058,
|
|
"n": 299
|
|
},
|
|
"upload": {
|
|
"p50": 0.2501,
|
|
"p95": 0.4001,
|
|
"max": 2.38,
|
|
"mean": 0.2757,
|
|
"n": 300
|
|
},
|
|
"paint": {
|
|
"p50": 1.109,
|
|
"p95": 1.6249,
|
|
"max": 23.3764,
|
|
"mean": 1.2774,
|
|
"n": 301
|
|
},
|
|
"latency": {
|
|
"p50": 33.0697,
|
|
"p95": 33.7423,
|
|
"max": 112.6438,
|
|
"mean": 33.3061,
|
|
"n": 299
|
|
}
|
|
},
|
|
"compose_count": 299,
|
|
"compose_note": "compose/compose_sample/compose_normals are the composer's own timers, collected on the worker thread; compose_wall adds the requested delay. latency is submit-to-paint and therefore includes the frame-rate limiter.",
|
|
"display": {
|
|
"superseded_display_frames": 1,
|
|
"stale_frames": 0,
|
|
"invalid_frames": 0,
|
|
"max_inflight_composes": 1,
|
|
"mailbox_capacity": 1,
|
|
"frames_presented": 298
|
|
},
|
|
"crypto_backend": "49.0.0",
|
|
"verdict": "ok",
|
|
"exit_code": 0
|
|
},
|
|
"real_asset_cpu": {
|
|
"mode": "cpu",
|
|
"frames_requested": 500,
|
|
"scene": "package:D:\\orisys_ws\\.repro\\build\\finger-display-1.0.0.oryscene",
|
|
"mesh": {
|
|
"sensing_vertices": 1032,
|
|
"sensing_triangles": 1974,
|
|
"field_domain_hw": [
|
|
300,
|
|
280
|
|
]
|
|
},
|
|
"timings_ms": {
|
|
"compose": {
|
|
"p50": 0.4975,
|
|
"p95": 0.748,
|
|
"max": 0.9371,
|
|
"mean": 0.5416,
|
|
"n": 500
|
|
},
|
|
"compose_sample": {
|
|
"p50": 0.1531,
|
|
"p95": 0.2425,
|
|
"max": 0.3929,
|
|
"mean": 0.1672,
|
|
"n": 500
|
|
},
|
|
"compose_normals": {
|
|
"p50": 0.3049,
|
|
"p95": 0.4742,
|
|
"max": 0.6302,
|
|
"mean": 0.3376,
|
|
"n": 500
|
|
},
|
|
"compose_wall": {
|
|
"p50": 0.4992,
|
|
"p95": 0.7509,
|
|
"max": 0.9399,
|
|
"mean": 0.5436,
|
|
"n": 500
|
|
}
|
|
},
|
|
"verdict": "ok",
|
|
"exit_code": 0
|
|
},
|
|
"grid_20k_gui": {
|
|
"profile_requested": "desktop33",
|
|
"frames_requested": 150,
|
|
"viewport_px": [
|
|
900,
|
|
700
|
|
],
|
|
"slow_compose_ms": 0.0,
|
|
"max_fps_requested": 30,
|
|
"scene": "grid:20000",
|
|
"context": {
|
|
"profile_used": "desktop33",
|
|
"vendor": "NVIDIA Corporation",
|
|
"renderer": "NVIDIA GeForce RTX 4080 SUPER/PCIe/SSE2",
|
|
"gl_version": "3.3.0 NVIDIA 610.88",
|
|
"glsl_version": "3.30 NVIDIA via Cg compiler",
|
|
"software_renderer": false,
|
|
"max_texture_size": 32768,
|
|
"device_pixel_ratio": 1.0,
|
|
"qt_platform": "windows"
|
|
},
|
|
"mesh": {
|
|
"sensing_vertices": 20022,
|
|
"sensing_triangles": 39480,
|
|
"housing_triangles": 0,
|
|
"field_domain_hw": [
|
|
142,
|
|
141
|
|
],
|
|
"estimated_gpu_bytes": 1756192
|
|
},
|
|
"timings_ms": {
|
|
"submit": {
|
|
"p50": 0.1347,
|
|
"p95": 0.249,
|
|
"max": 0.5272,
|
|
"mean": 0.146,
|
|
"n": 150
|
|
},
|
|
"compose": {
|
|
"p50": 98.7824,
|
|
"p95": 99.9672,
|
|
"max": 116.6785,
|
|
"mean": 78.3176,
|
|
"n": 31
|
|
},
|
|
"compose_sample": {
|
|
"p50": 16.1169,
|
|
"p95": 16.573,
|
|
"max": 23.1074,
|
|
"mean": 11.5654,
|
|
"n": 31
|
|
},
|
|
"compose_normals": {
|
|
"p50": 82.5348,
|
|
"p95": 83.6703,
|
|
"max": 99.7443,
|
|
"mean": 63.5145,
|
|
"n": 31
|
|
},
|
|
"compose_wall": {
|
|
"p50": 98.8445,
|
|
"p95": 99.9764,
|
|
"max": 116.6866,
|
|
"mean": 78.3673,
|
|
"n": 31
|
|
},
|
|
"upload": {
|
|
"p50": 0.2777,
|
|
"p95": 0.6052,
|
|
"max": 2.0555,
|
|
"mean": 0.3328,
|
|
"n": 150
|
|
},
|
|
"paint": {
|
|
"p50": 0.7098,
|
|
"p95": 1.7044,
|
|
"max": 12.5557,
|
|
"mean": 1.035,
|
|
"n": 151
|
|
},
|
|
"latency": {
|
|
"p50": 115.0327,
|
|
"p95": 130.3314,
|
|
"max": 134.1893,
|
|
"mean": 94.0401,
|
|
"n": 31
|
|
}
|
|
},
|
|
"compose_count": 31,
|
|
"compose_note": "compose/compose_sample/compose_normals are the composer's own timers, collected on the worker thread; compose_wall adds the requested delay. latency is submit-to-paint and therefore includes the frame-rate limiter.",
|
|
"display": {
|
|
"superseded_display_frames": 118,
|
|
"stale_frames": 0,
|
|
"invalid_frames": 0,
|
|
"max_inflight_composes": 1,
|
|
"mailbox_capacity": 1,
|
|
"frames_presented": 30
|
|
},
|
|
"crypto_backend": "49.0.0",
|
|
"verdict": "ok",
|
|
"exit_code": 0
|
|
},
|
|
"grid_20k_cpu": {
|
|
"mode": "cpu",
|
|
"frames_requested": 200,
|
|
"scene": "grid:20000",
|
|
"mesh": {
|
|
"sensing_vertices": 20022,
|
|
"sensing_triangles": 39480,
|
|
"field_domain_hw": [
|
|
142,
|
|
141
|
|
]
|
|
},
|
|
"timings_ms": {
|
|
"compose": {
|
|
"p50": 6.1455,
|
|
"p95": 6.3987,
|
|
"max": 6.5786,
|
|
"mean": 6.1376,
|
|
"n": 200
|
|
},
|
|
"compose_sample": {
|
|
"p50": 1.058,
|
|
"p95": 1.145,
|
|
"max": 1.4462,
|
|
"mean": 1.0639,
|
|
"n": 200
|
|
},
|
|
"compose_normals": {
|
|
"p50": 4.9096,
|
|
"p95": 5.072,
|
|
"max": 5.1775,
|
|
"mean": 4.8943,
|
|
"n": 200
|
|
},
|
|
"compose_wall": {
|
|
"p50": 6.2412,
|
|
"p95": 6.4834,
|
|
"max": 6.6717,
|
|
"mean": 6.2281,
|
|
"n": 200
|
|
}
|
|
},
|
|
"verdict": "ok",
|
|
"exit_code": 0
|
|
}
|
|
},
|
|
"findings": [
|
|
"The shipped 1032-vertex surface composes in 0.5 ms p50 / 0.75 ms p95 and the display holds its 30 fps cap (latency p50 33 ms = the cap, not the cost).",
|
|
"A 19881-vertex / 39200-triangle surface composes in 6.1 ms p50 / 6.4 ms p95, i.e. about 18% of a 33 ms frame: the design document's 20k budget is met on this machine with room for the upload and the paint.",
|
|
"The acquisition thread's own cost (submit_packet, including the |flow| computation and the mailbox) is 0.14-0.17 ms p50 and under 0.4 ms p95 while the composer is deliberately 50 ms slow: the display cannot push back on acquisition.",
|
|
"At 20k vertices the normals are 80% of the compose (4.9 ms of 6.1 ms): the obvious optimisation if a larger surface is wanted is the normal recomputation, not the UV sampling.",
|
|
"The queue bound holds: at most one compose in flight and a capacity-one mailbox, with every dropped frame counted as a display drop (superseded_display_frames) and none of them counted as a lost sample."
|
|
],
|
|
"not_measured_here": [
|
|
"GPU memory over time (the long-run report covers RSS and the queue bound; this report has the estimated buffer size from the renderer)",
|
|
"the ARM boards: probe_gl.py and this benchmark are ready to run there, and the platform lock can be compiled from the resulting probe report",
|
|
"a 20k-vertex surface with a *calibrated* displacement (the adapters do not produce one; the composer's deformation path is covered by unit tests)"
|
|
]
|
|
}
|