转载

go的chan深度解析,已经go disruptor不适合go的高并发模式

首先看下go的chan内部源码 go的chan深度解析,已经go disruptor不适合go的高并发模式 chan 内部是一个固定长度的数组,这个数组又是环形队列。qcount数组实际大小,dataqsize数组长度,buf为实际数组指针,sendx,recvx为接受发送索引,用于环形队列,自增超过dataqsize索引清0,recvq,sendq链表保存等待或者发送groutinue信息,他是先进先出的队列。lock,go的chan的锁实际是自旋锁。

让我们在看下lock的代码

go的chan深度解析,已经go disruptor不适合go的高并发模式

go的自旋锁实际采用tas testandset,当tas次数<4次的时候,procyyield内部汇编是空转cpu,<5    yield交出时间片给其他groutinue,其他情况,就一直tas一直到成功为止

go chan 再写入和读取都是自旋锁,锁队列。

环形队列,如下

go的chan深度解析,已经go disruptor不适合go的高并发模式

在探讨下godisruptor为什么不适合go的并发开发

1.首先语法,godisruptor无锁环形队列,写法不能再select了,只能groutine + for模式

2.godisruptor内部没有优化好,再消费者,实际他只是sleep等待,具体源码如下

go的chan深度解析,已经go disruptor不适合go的高并发模式

3.godisruptor生产者 一次入队10个的情况下性能比chan要好10个倍数。但是再 多生产者但消费者,生产者实际产生的io,一般都是一条一条入的实际情况下,性能和chan差不都,自旋和无锁区别,自旋消耗再锁操作,会出现空转cpu,无锁利用cpucacheline+环形队列+cas,性能更加,利用upper和lower一个作为生产者索引,一个做消费者索引,当消费者索引<生产者索引的时候,取数据,内部这两个变量是一直累加&数组长度,无锁也只要cas这两个索引就ok,就避免了统一时刻操作数组同一个索引。

数据如下 go的chan深度解析,已经go disruptor不适合go的高并发模式 2千万数据, 5个生产者一个消费者   单入的情况下,godisruptor每秒5790387吞吐,chan每秒吞吐3696857,一个倍级

对比数据,你是选godisruptor还是chan

原文  https://studygolang.com/articles/22537
正文到此结束
Loading...