主要观点:
- 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) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。