“go:nosplit”是 Go 语言中的一个注释或标记,用于指示编译器在某些情况下不要进行特定的代码分割或优化。它可以用于特定的代码段或函数,以确保在特定的上下文中,代码以特定的方式执行,而不会被编译器进行不必要的分割或优化。 具体的用途和效果可能因

主要观点:

  • Go 有特殊的指令语法,但只是注释,有多种类型的指令,如//go:noinline等。
  • //go:nosplit指令标记函数为“非分裂函数”,其行为影响函数的栈溢出检查和性能。
  • //go:nosplit函数不加载和分支于runtime.g.stackguard0,假设自己有足够的栈,调用速度更快,但可能导致栈溢出等问题。
  • 虚拟//go:nosplit函数可通过虚拟函数调用绕过链接器栈检查,但可能引发段错误等问题。
  • //go:nosplit还会影响函数是否被视为“不安全”,可能导致程序挂起或活锁等问题。

关键信息:

  • Go 栈为新的 goroutine 分配小栈且动态增长,易溢出,每个函数周围有特定的栈溢出处理代码。
  • 不同类型指令及其文档位置,如//go:noinline等在gc的文档注释中。
  • //go:nosplit指令的作用和示例代码,以及其对函数性能和栈行为的影响。
  • 虚拟//go:nosplit函数的示例和可能的问题。
  • //go:nosplit对函数“不安全”标记的影响及相关示例程序。

重要细节:

  • 正常程序代码可使用//go:nosplit注解,但行为未很好规定。
  • 分段栈在 Go 早期存在问题,现已被改进。
  • 栈检查指令会增加约 2%的成本,缓存未命中会使性能差异更大。
  • Go 链接器有关于//go:nosplit函数链的栈检查。
  • 开启模糊测试可能使原本正常的代码无法链接。
  • 异步抢占与//go:nosplit函数相关,可能导致程序挂起等问题。
  • 存在一些与//go:nosplit相关的未记录的副作用,如导致不必要的栈空间分配等。
阅读 41
0 条评论