您的位置 首页 golang

联蔚科技干货—浅谈golang1.14的特性及改进

工程师在迭代中都有遇到过底层关键包升级的问题,譬如consul,micro,go-config等,今天就来了解一下最新的GO1.14的特性和改进。

今年2月golang发布了GO1.14版本,随后在3月的TIOBE编程语言排行榜上Go进入了TOP10,而去年同期Go仅排行在第18位。Go在这样的一个时间节点能进入TOP10,对于Gopher和Go社区来说,是一个不错的结果。这从一定的程度上说明,Go在努力耕耘十年后,能在世界主流编程语言中牢据自己的一个位置。

嵌入接口的方法集可以重叠

这个变化的背后是一个很朴素的思想。我们先来看下面的代码:

定义A和B两个接口,方法集中都包含有string()string这个方法。在这样的情况下,我们如果想定义一个如上图的方法集合为Union(a, b)的接口O ,我们在Go1.13及之前的版本中只能使用第(2)种方式,即只能在接口O中重新书写一遍所有的方法原型,而无法像第(1)种方式那样使用嵌入接口的简洁方式进行。

但是需要注意,对于overlapping interface的支持仅限于接口定义,如果在struct定义中嵌入interface的话,是不被允许的。

举个例子:

对于结构体中嵌入接口的方法集是否存在overlap,GO1.14将这个检查延迟到为结构体选择method的执行者环节了。使用结构体时会给出错误:ambiguous selector xxxxxxx 。

这时我们让Foo结构体override 一个string() 方法,那么即便接口J和I存在overlap 也没有关系,因为编译器可以知道Foo实例具体执行哪个。

支持异步的抢占式调度

golang最大的特性就是协程,通过协程可以在用户态中最大程度的利用用户线程来增加程序的效率。此次改进的地方正是对协程的调度机制GMP的改进。

解释这个特性之前,先简单介绍一下其中的关键词。在调度器中,有三个角色M(thread)、G(goroutine)和P(Processor)。前两者都比较熟悉了,第三位Processor,它是包含了运行goroutine的资源,当线程想运行goroutine,必须先获取P,当然P中还包含了可运行的G队列。M必须持有P才能执行G中的代码,P有自己本地的一个运行队列runq,由可运行的G组成,下图展示了线程M、处理器P和goroutine的关系。

我们再来看一段代码:

在当前系统只有一个P的情况下,代码中for所在goroutine将持续占据该P,使得main goroutine中的routine下的代码得不到调度,因此我们无法看到 Connext PanCloud NO.1! 字样输出。换一句话说在Go1.14之前,Go1.13及以前的版本的抢占是”协作式“的,这种协作式只在有函数调用的地方才能插入“抢占”代码(埋点),而for没有给编译器插入抢占代码的机会。抢占式调度是不会使一个没有主动放弃执行权、且不参与任何函数调用的goroutine被抢占。那这会导致GC在等待所有goroutine停止时等待时间过长,从而导致GC延迟;甚至在一些特殊情况下,导致在STW时死锁。

Go1.14采用了基于系统信号的异步抢占调度,系统信号可能在代码执行到任意地方发生,在Go runtime能cover到的地方,Go runtime自然会处理好这些系统信号。而GMP调度器的工作原理就是处理器P从本地队列中依次选择goroutine放到线程M上调度执行,每个P维护的G可能是不均衡的,为此调度器维护了一个全局G队列,当P执行完本地的G任务后,会尝试从全局队列中获取G任务运行(需要加锁),当P本地队列和全局队列都没有可运行的任务时,会尝试偷取其他P中的G到本地队列运行(任务窃取)。

Defer性能得以继续优化

Go1.13中defer性能得到理论上30%的提升。我们还用那个例子来看看Go1.14与Go1.13相比defer性能又有多少提升,同时再看看使用defer和不使用defer的对比:

基准测试Benchmark

Go1.13 defer性能测试数据

Go1.14 defer性能测试数据

我们看到,Go1.14的defer性能比Go1.13还有大幅提升,并且已经与不使用defer的性能相差无几了,Go1.14使用defer关闭channel几乎0开销!关于这一改进,官方给出的回应是:Go1.14提高了defer的大多数用法的性能,几乎0开销!defer已经可以用于对性能要求很高的场景了。这也是Go官方和我一起鼓励大家在性能敏感的代码执行路径上也大胆使用defer的原因。

除此之外Go1.14中还对内置的定时器进行了优化,修正了遵循逻辑:将timer分配到每个P上,降低锁竞争;去掉timer thread,减少了上下文切换的开销。甚至是go module都已经production ready了。这对于我们当前的技术架构是个极好的消息。

此次分享就先告一段落,希望今天的介绍能够对大家运用golang1.14有所帮助。如果有问题的小伙伴们可以留言,欢迎一起交流。

文章来源:智云一二三科技

文章标题:联蔚科技干货—浅谈golang1.14的特性及改进

文章地址:https://www.zhihuclub.com/97685.shtml

关于作者: 智云科技

热门文章

网站地图