在项目中的一些思考:线程池里究竟该放多少线程?

2016-07-09 13:32:23 +08:00
 zwh8800

在最近的使用 golang 开发中,发现 goroutine 实际上解决的只是线程资源的调度,避免大量线程带来的资源瓶颈。

而在实际开发中,更多遇到的问题是其他的资源瓶颈带来的。比如 tcp 连接、数据库连接、带锁的资源等。并不只是一个简单的线程资源的问题,当使用这些资源时,还是需要要用到使用传统线程时的一些思想/技术。

所以说感觉并发这个问题是个大坑,软件工程没有银弹。

当然了, golang 能合理调度线程资源已经是语言的一个很大进步了,不用让程序员自己费心调度线程。

具体的思考我写到博客里了,这里贴代码和图不太方便,我放个链接吧:

并发难 | 池里究竟该放多少线程?https://lengzzz.com/note/concurrency-roadblock-how-many-threads-should-be-in-pool

只是个人观点,抛砖引玉,大家多多讨论一下。

软件工程没有银弹,路漫漫其修远兮,吾将上下而求索。

2655 次点击
所在节点    Go 编程语言
24 条回复
des
2016-07-09 13:39:58 +08:00
一般性而言, CPU 密集运算,和 CPU 核数相等就行了
tiancaiamao
2016-07-09 13:44:37 +08:00
最佳线程数量 = (线程等待时间 + 线程 CPU 时间) / 线程 CPU 时间 * CPU 数量
平均响应时间 = 并发线程数 / 最佳线程数 * 最佳线程响应时间

最后, LZ 研究的东西跟线程池半毛钱关系都没有
zwh8800
2016-07-09 13:45:32 +08:00
@des 是的,运算密集型的应用应该是最可控的。但实际中都是复杂到不行的 IO 密集型应用😳
zwh8800
2016-07-09 13:53:56 +08:00
@tiancaiamao

这个公式也并没有考虑到 IO 资源的瓶颈问题。我在实际中首先使用单线程做了 pprof 。总执行时间 130s ,卡在 Syscall 上的时间是 90s 。

那么按道理来说应该是 130 / (130 - 90) * 核数 = 52 。

但实际上,开 32 个线程,数据库就崩了。这是 IO 资源有瓶颈导致的。

好吧,确实和有没有线程池关系不大,重点在线程数量上。
kamikat
2016-07-09 14:24:45 +08:00
IO 密集优化的线程池大小把平均 IO 等待时间和 CPU 时间的比值乘到 CPU 核心数就可以了(好像和 @tiancaiamao 回复里的公式差不多… )。
开 32 个线程数据库就崩了这种事情… 是数据库的瓶颈。
mengzhuo
2016-07-09 14:28:52 +08:00
goroutine 和一般线程不是一个东西 基本不需要计算这些量
zwh8800
2016-07-09 14:33:53 +08:00
@kamikat 嗯嗯,确实是数据库的,但有时更复杂,并发高了之后 connect 函数也会莫名其妙超时。

@mengzhuo 我以前也是你这种想法,直到发现 goroutine 只解决了线程资源瓶颈的问题。其他 IO 资源的瓶颈问题还是需要自行解决的。
kamikat
2016-07-09 14:46:11 +08:00
@zwh8800 LZ 想问的大概是数据库的连接池开多大,我自己倾向认为数据库是 CPU 密集型的(数据库对 IO 什么的有各种的优化来着),所以一般是连接数=核心数。榨干机器性能的任务就交给数据库来处理了,比较不赞同增加连接数逼迫数据库榨干机器性能的方法。
magicdawn
2016-07-09 15:02:11 +08:00
mengzhuo
2016-07-09 15:07:31 +08:00
@zwh8800 数据库的连接肯定得限制的,还有文件加锁都属于常识啦。楼主你这个吐槽的对象都不是同一个好么
reus
2016-07-09 17:18:14 +08:00
数据库崩,就去调数据库参数
connect 超时,就加网络带宽
和 golang 其实没什么关系
而且,把 goroutine 看成线程就对了,性质基本一致
shyling
2016-07-09 18:48:44 +08:00
是问线程池的大小吧= =
zwh8800
2016-07-09 19:33:19 +08:00
@mengzhuo

我的意思是,各种对并发支持的好的语言,也只是在 “平衡线程资源” 这一点上做到了优化。对于实际中更常见的 IO 资源瓶颈引来的问题,还是得自己动手调。

@reus

调并发量本身就是调并发程序必不可少的一步,数据库参数再怎么调也架不住程序瞎搞啊。


@shyling 对的
wizardforcel
2016-07-09 20:10:32 +08:00
这个就需要你手动调啊,我的电脑虽然是四核,但以前写爬虫的时候发现 10 个左右更快一点。
louk78
2016-07-09 21:56:24 +08:00
和线程池有个一毛钱关系吗?线程不就是时间片,不装逼就不能活了
Comdex
2016-07-09 23:01:50 +08:00
这个时候又要推一下 goroutine pool lib 了 https://github.com/Comdex/octopus
wander2008
2016-07-10 09:19:13 +08:00
这时候就应该去了解一下 java
zwh8800
2016-07-10 12:26:20 +08:00
@louk78 手动黑人问号

@Comdex 嗯嗯,我也用了一个 goroutine pool https://github.com/go-playground/pool 才 100 多行,很轻量

@wander2008 java 转的 golang ,以前写 java 和 c#
wander2008
2016-07-10 14:38:53 +08:00
@zwh8800 你用 java 多久了?
zwh8800
2016-07-10 18:35:31 +08:00
@wander2008 上家公司用 java , spring mvc 什么的。在那里工作了 7 个月。之前在学校也有做过。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/291336

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX