Go Wiki: AssemblyPolicy

本文档描述了何时以及如何将汇编代码添加到 Go 语言的加密库中。

总的来说,规则如下:

  • 我们更倾向于可移植的 Go 代码,而不是汇编。汇编代码意味着需要维护(N 个库 * M 种架构)的工作量,而不仅仅是 N 个库。
  • 尽量减少汇编的使用。我们宁愿用少量汇编实现 50% 的速度提升,也不愿用两倍的汇编来实现 55% 的速度提升。在提交信息中解释将汇编/Go 边界设置在那里,并用基准测试支持该决定。
  • 使用更高级别的程序来生成非平凡的汇编代码,这些程序可以是独立的 Go 程序,也可以是 go get-able 的程序,例如 avo。其他可重现的进程(如形式化验证的代码生成器)的输出也将被考虑。提前在问题跟踪器上讨论实现策略。
  • 使用称作“单元”的小型、可测试的代码块(25-75 行),并由用 Go 编写的高级逻辑调用。如果使用由 Go 编写的逻辑调用的、小型、可测试的函数速度太慢,则使用小型、可测试的汇编单元,并配有 Go 兼容的包装器,以便 Go 测试仍然可以测试单个单元。
  • 任何汇编函数都需要一个参考的 Go 实现,该实现与汇编代码并行测试。遵循 TargetSpecific 的结构和测试实践。
  • 汇编单元和参考 Go 实现的接口必须跨架构相同,除非平台具有根本不同的能力(例如高级加密指令)。
  • 除非 Go 安全团队明确承诺拥有特定实现的维护权,否则外部贡献者必须承诺维护它。如果需要更改(例如作为更广泛重构的一部分),并且维护者不可用,则将删除该汇编代码。
  • 代码必须在我们 CI 中进行测试。这意味着需要有支持这些指令的构建器,并且如果有多个(或备用)路径,它们必须分别进行测试。(提示:使用 GODEBUG=cpu.X=off 来禁用 CPU 功能检测。)
  • 在 Go 代码中记录实现为何需要汇编(特定的性能优势、对指令的访问等),以便随着编译器改进,我们可以重新评估。

并非所有当前在标准库中的汇编都符合此策略。在现有汇编更新到符合规定之前,将不鼓励更改。新的汇编必须符合规定。


此内容是 Go Wiki 的一部分。