主要观点:
- 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相关的未记录的副作用,如导致不必要的栈空间分配等。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用。你还可以使用@来通知其他用户。