golang多核陷阱一例
lubia · · 3400 次点击 · · 开始浏览同时发布在独立博客。
以前一直以为,在Golang中,针对高并发的情况,采用多核处理一定效果最优,但是项目实践证明事实不是这样的。
在Sniper项目中(一个结合了ab和siege优点的http负载测试工具),原来一直设置cup使用数为系统cpu总数:
runtime.GOMAXPROCS(runtime.NumCPU())
在与ab的性能比较中一直有较大差距,GET请求局域网的一个10k大小的文件:
以下是ab的性能,并发100,总请求100k,执行时间16.082秒
Concurrency Level: 100
Time taken for tests: 16.082 seconds
Complete requests: 100000
Failed requests: 0
Write errors: 0
Total transferred: 1035500000 bytes
HTML transferred: 1024000000 bytes
Requests per second: 6218.04 [#/sec] (mean)
Time per request: 16.082 [ms] (mean)
Time per request: 0.161 [ms] (mean, across all concurrent requests)
Transfer rate: 62878.74 [Kbytes/sec] received
接下来采用sniper测试,设置runtime.GOMAXPROCS(runtime.NumCPU())
Transactions: 100000 hits
Availability: 100.00 %
Elapsed time: 20.82 secs
TotalTransfer: 0.00 MB
HTMLTransfer: 0.00 MB
Transaction rate: 4802.45 trans/sec
Throughput: 0.00 MB/sec
Successful: 100000 hits
Failed: 0 hits
TransactionTime: 0.00021 secs(mean)
ConnectionTime: 0.00010 secs(mean)
RequestTime: 0.00000 secs(mean)
ResponseTime: 0.00011 secs(mean)
可以看到测试同样的服务器,使用全部的cpu,sniper耗时20.82秒。
最后我再设置runtime.GOMAXPROCS(1)
Transactions: 100000 hits
Availability: 100.00 %
Elapsed time: 16.71 secs
TotalTransfer: 0.00 MB
HTMLTransfer: 0.00 MB
Transaction rate: 5985.03 trans/sec
Throughput: 0.00 MB/sec
Successful: 100000 hits
Failed: 0 hits
TransactionTime: 0.00017 secs(mean)
ConnectionTime: 0.00003 secs(mean)
RequestTime: 0.00000 secs(mean)
ResponseTime: 0.00014 secs(mean)
可以看到,sniper的执行时间降到16.71秒,降低了20%。
没想到优化了这么久的性能最后竟然通过这样的办法前进一大步!
出现这种情况原因在哪里?
目前我也解释不清楚,可能跟CPU的上下文切换有关,详细的原理需要再研究。有知道原理原因的请指教。
update:
一个可能的原因:在这里看到
和所有其他并发框架里的协程一样,goroutine里所谓"无锁"的优点只在单线程下有效,如果$GOMAXPROCS > 1并且协程间需要通信,Go运行库会负责加锁保护数据。sniper存在大量的协程间通信,可能是锁影响了性能。
有疑问加站长微信联系(非本文作者)
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
关注微信- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码` - 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传
收入到我管理的专栏 新建专栏
同时发布在独立博客。
以前一直以为,在Golang中,针对高并发的情况,采用多核处理一定效果最优,但是项目实践证明事实不是这样的。
在Sniper项目中(一个结合了ab和siege优点的http负载测试工具),原来一直设置cup使用数为系统cpu总数:
runtime.GOMAXPROCS(runtime.NumCPU())
在与ab的性能比较中一直有较大差距,GET请求局域网的一个10k大小的文件:
以下是ab的性能,并发100,总请求100k,执行时间16.082秒
Concurrency Level: 100
Time taken for tests: 16.082 seconds
Complete requests: 100000
Failed requests: 0
Write errors: 0
Total transferred: 1035500000 bytes
HTML transferred: 1024000000 bytes
Requests per second: 6218.04 [#/sec] (mean)
Time per request: 16.082 [ms] (mean)
Time per request: 0.161 [ms] (mean, across all concurrent requests)
Transfer rate: 62878.74 [Kbytes/sec] received
接下来采用sniper测试,设置runtime.GOMAXPROCS(runtime.NumCPU())
Transactions: 100000 hits
Availability: 100.00 %
Elapsed time: 20.82 secs
TotalTransfer: 0.00 MB
HTMLTransfer: 0.00 MB
Transaction rate: 4802.45 trans/sec
Throughput: 0.00 MB/sec
Successful: 100000 hits
Failed: 0 hits
TransactionTime: 0.00021 secs(mean)
ConnectionTime: 0.00010 secs(mean)
RequestTime: 0.00000 secs(mean)
ResponseTime: 0.00011 secs(mean)
可以看到测试同样的服务器,使用全部的cpu,sniper耗时20.82秒。
最后我再设置runtime.GOMAXPROCS(1)
Transactions: 100000 hits
Availability: 100.00 %
Elapsed time: 16.71 secs
TotalTransfer: 0.00 MB
HTMLTransfer: 0.00 MB
Transaction rate: 5985.03 trans/sec
Throughput: 0.00 MB/sec
Successful: 100000 hits
Failed: 0 hits
TransactionTime: 0.00017 secs(mean)
ConnectionTime: 0.00003 secs(mean)
RequestTime: 0.00000 secs(mean)
ResponseTime: 0.00014 secs(mean)
可以看到,sniper的执行时间降到16.71秒,降低了20%。
没想到优化了这么久的性能最后竟然通过这样的办法前进一大步!
出现这种情况原因在哪里?
目前我也解释不清楚,可能跟CPU的上下文切换有关,详细的原理需要再研究。有知道原理原因的请指教。
update:
一个可能的原因:在这里看到
和所有其他并发框架里的协程一样,goroutine里所谓"无锁"的优点只在单线程下有效,如果$GOMAXPROCS > 1并且协程间需要通信,Go运行库会负责加锁保护数据。sniper存在大量的协程间通信,可能是锁影响了性能。