golang奇技淫巧笔记】- "//go:" 随便聊聊

在座的看看官,首先,本文毫无技术含量,只是作者做个放置忘记的参考笔记用的,所以,你们还是别往下看了!谢谢!

我们如果查看过go源码的一般都会看到有 //go: xxx 之类的注释。那么这种注释到底是干嘛用的呢?其实啊,这种注释都是有特殊含义的,一般就是为了提醒 编译器对代码做相应的处理的。来,下面我们就说说这些特殊的注释吧。

 

//go:noinline

表示不做内联

(什么是内联? Inline,是在编译期间发生的,将函数调用调用处替换为被调用函数主体的一种编译器优化手段)

内联的好坏:

好处: 

  • 减少函数调用的开销,提高执行速度。
  • 复制后的更大函数体为其他编译优化带来可能性,如 过程间优化
  • 消除分支,并改善空间局部性和指令顺序性,同样可以提高性能。

坏处:

  • 代码复制带来的空间增长。
  • 如果有大量重复代码,反而会降低缓存命中率,尤其对 CPU 缓存是致命的。

简单来说,对于短小而且工作较少的函数,使用内联是有效益的

自动内联的例子:

package main



func main() {

  appendStr("ss")

}


func appendStr(str string) string {

	return "new" + str
}

在命令行编译: go tool compile -S inline.go > inline.s

那么我们不需要做内联的时候,则直接在 appendStr( ) 函数上加上注释  //go:noinline

package main

func main () {
    
    appendStr("ss")

}

//go:oninline
func appendStr(word string) string {
    return "new " + word
}

执行编译之后:  go tool compile -S noinline.go > noinline.s

 

//go:nosplit

跳过栈溢出检测。

什么是栈溢出?

一个 Goroutine 的起始栈大小是有限制的,且比较小的,才可以做到支持并发很多 Goroutine,并高效调度。
stack.go 源码中可以看到,_StackMin 是 2048 字节,也就是 2k,它不是一成不变的,当不够用时,它会动态地增长。
那么,必然有一个检测的机制,来保证可以及时地知道栈不够用了,然后再去增长。
回到话题,nosplit 就是将这个跳过这个机制。
 

显然地,不执行栈溢出检查,可以提高性能,但同时也有可能发生 stack overflow 而导致编译失败

 

//go:noescape

禁止逃逸。

注意: 它必须指示一个只有声明没有主体的函数

什么是逃逸?Go 相比 C、C++ 是内存更为安全的语言,主要一个点就体现在它可以自动地将超出自身生命周期的变量,从函数栈转移到堆中,逃逸就是指这种行为。

最显而易见的好处是,GC 压力变小了。
因为它已经告诉编译器,下面的函数无论如何都不会逃逸,那么当函数返回时,其中的资源也会一并都被销毁。
不过,这么做代表会绕过编译器的逃逸检查,一旦进入运行时,就有可能导致严重的错误及后果。

 

//go:norace

跳过竞态检测。 除了减少编译时间,没鸡毛用。

 

//go:notinheap

用于类型声明

表示这个类型不允许从 GC 堆上进行申请内存

在运行时中常用其来做较低层次的内部结构,避免调度器和内存分配中的写屏障。能够提高性能。

//go:nowritebarrierrec  和  //go:yeswritebarrierrec

搞不懂这两个,应该是和 写屏障 相关的谢谢! 

 

//go:linkname 当前函数名/变量名【localname】 被关联的函数名/变量名(包含包名)【importpath.name

 

黑魔法。由于这个伪指令,可以破坏类型系统和包模块化。因此只有引用了 unsafe 包才可以使用

简单来讲,就是   importpath.name 是 localname 的符号别名,编译器实际上会调用 localname 。

注意: linkname 是双向的,具有导出 和导入 两种使用方式。

导出的不能被作为导入,但是导入的可以作为多个导入, 仅限函数,变量不行

参考:

 http://www.iikira.com/2019/02/10/golang-note-4-golinkname/

https://studygolang.com/articles/12134

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值