性能与体积

Viva 的预算、实际测过的结果、未达标的地方,以及自己的代码里该避免什么。

Viva 为小体积和低空闲开销而设计。这些是设计目标,不是承诺。下面每个结果都来自仓库里的报告,对应报告中写明的机器和构建方式;它们是那台机器上的基线,不是对你机器的保证。

预算

对一个最小的原生应用:

预算 目标
剥离后的可执行文件 不超过 4 MiB(超过 8 MiB 需要复核)
预热启动到首个可交互帧 不超过 50 ms
空闲常驻内存 不超过 15 MiB
空闲 CPU、GPU 提交与呈现 实际为零
空闲时框架的 goroutine 不超过 2 个
未变化的一帧 不布局、不重建场景、不提交 GPU

目标冲突时的顺序是:低内存,然后是运行性能,然后是小体积产物,然后是正确性,然后是易用性和跨平台一致性,最后才是可选的浏览器目标。

实际测过什么

M0 是最小的 macOS 窗口:一次 Metal 清屏与呈现,没有任何组件。测量环境是 Apple 芯片、macOS 15.5、Go 1.26.5,构建参数为 -trimpath -ldflags='-s -w -buildid='。

指标 结果 目标 结论
剥离后的可执行文件 1,697,506 bytes 不超过 4 MiB 达标
稳定后的 CPU 0.0% 实际为零 达标
空闲 GPU 提交 首次呈现后为 0 零 达标
真实 Metal 呈现后的物理内存占用 26.3–26.8 MiB 不超过 15 MiB 未达标
首个调度帧 123.075–373.643 ms 预热不超过 50 ms 未达标

报告对这两项未达标写得很明确。更早出现过的 15 MiB 数字是在尚未提交任何 Metal 命令时测的,已被否决,不作为基线。AppKit 与 Metal 的固定开销还没有和 Viva 自身的部分分开,所以内存目标保持不变,但目前未达到。完整报告含机器信息和复现命令,见仓库中的 docs/benchmarks/。

保留式场景(M1)清空一个未变化的 10,000 节点场景用时 2.012 ns 且无分配,更新 10,000 个节点中的一个用时 12.39 ns 且无分配。

自己的代码里该避免什么

只有应用也做到,Viva 才能把空闲开销保持为零。

  • 不要靠定时器重绘。 状态变化时调用 Invalidator.Invalidate,其余时间让窗口休眠。
  • 不要在 Paint 里分配内存。 它在每次重绘时运行,框架自己的稳态路径也写成了尽量少分配、接近零。复用缓冲区,让每帧的工作量与变化量成正比。
  • 回调要短。 它们在窗口线程上运行。慢的工作放到其他 goroutine,再通过 OnWake 发布结果。
  • 只链接用到的东西。 可选子系统放在各自的包和构建标签里,没用到的不会给你的二进制增加代码。

复现

benchmarks/ 目录里有 macOS 和 Linux 基线背后的脚本,每份报告都写明了产生它的命令。viva build 会单独报告程序本身的大小,不含周围的其他东西。