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

bobohume · · 2960 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

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

让我们在看下lock的代码

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

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

环形队列,如下

 

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

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

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

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

数据如下2千万数据, 5个生产者一个消费者   单入的情况下,godisruptor每秒5790387吞吐,chan每秒吞吐3696857,一个倍级

 

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


有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

2960 次点击  
加入收藏 微博
1 回复  |  直到 2019-08-07 11:46:02
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传