Golang Go语言中在项目的一些思考:线程池里究竟该放多少线程?
在最近的使用 golang 开发中,发现 goroutine 实际上解决的只是线程资源的调度,避免大量线程带来的资源瓶颈。
而在实际开发中,更多遇到的问题是其他的资源瓶颈带来的。比如 tcp 连接、数据库连接、带锁的资源等。并不只是一个简单的线程资源的问题,当使用这些资源时,还是需要要用到使用传统线程时的一些思想/技术。
所以说感觉并发这个问题是个大坑,软件工程没有银弹。
当然了, golang 能合理调度线程资源已经是语言的一个很大进步了,不用让程序员自己费心调度线程。
具体的思考我写到博客里了,这里贴代码和图不太方便,我放个链接吧:
并发难 | 池里究竟该放多少线程?https://lengzzz.com/note/concurrency-roadblock-how-many-threads-should-be-in-pool
只是个人观点,抛砖引玉,大家多多讨论一下。
软件工程没有银弹,路漫漫其修远兮,吾将上下而求索。
Golang Go语言中在项目的一些思考:线程池里究竟该放多少线程?
更多关于Golang Go语言中在项目的一些思考:线程池里究竟该放多少线程?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
一般性而言, CPU 密集运算,和 CPU 核数相等就行了
更多关于Golang Go语言中在项目的一些思考:线程池里究竟该放多少线程?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
最佳线程数量 = (线程等待时间 + 线程 CPU 时间) / 线程 CPU 时间 * CPU 数量
平均响应时间 = 并发线程数 / 最佳线程数 * 最佳线程响应时间
最后, LZ 研究的东西跟线程池半毛钱关系都没有
是的,运算密集型的应用应该是最可控的。但实际中都是复杂到不行的 IO 密集型应用😳
这个公式也并没有考虑到 IO 资源的瓶颈问题。我在实际中首先使用单线程做了 pprof 。总执行时间 130s ,卡在 Syscall 上的时间是 90s 。
那么按道理来说应该是 130 / (130 - 90) * 核数 = 52 。
但实际上,开 32 个线程,数据库就崩了。这是 IO 资源有瓶颈导致的。
好吧,确实和有没有线程池关系不大,重点在线程数量上。
IO 密集优化的线程池大小把平均 IO 等待时间和 CPU 时间的比值乘到 CPU 核心数就可以了(好像和 回复里的公式差不多… )。
开 32 个线程数据库就崩了这种事情… 是数据库的瓶颈。
goroutine 和一般线程不是一个东西 基本不需要计算这些量
嗯嗯,确实是数据库的,但有时更复杂,并发高了之后 connect 函数也会莫名其妙超时。
我以前也是你这种想法,直到发现 goroutine 只解决了线程资源瓶颈的问题。其他 IO 资源的瓶颈问题还是需要自行解决的。
LZ 想问的大概是数据库的连接池开多大,我自己倾向认为数据库是 CPU 密集型的(数据库对 IO 什么的有各种的优化来着),所以一般是连接数=核心数。榨干机器性能的任务就交给数据库来处理了,比较不赞同增加连接数逼迫数据库榨干机器性能的方法。
数据库的连接肯定得限制的,还有文件加锁都属于常识啦。楼主你这个吐槽的对象都不是同一个好么
数据库崩,就去调数据库参数
connect 超时,就加网络带宽
和 golang 其实没什么关系
而且,把 goroutine 看成线程就对了,性质基本一致
是问线程池的大小吧= =
这个就需要你手动调啊,我的电脑虽然是四核,但以前写爬虫的时候发现 10 个左右更快一点。
和线程池有个一毛钱关系吗?线程不就是时间片,不装逼就不能活了
这个时候又要推一下 goroutine pool lib 了 https://github.com/Comdex/octopus
这时候就应该去了解一下 java
手动黑人问号
嗯嗯,我也用了一个 goroutine pool https://github.com/go-playground/pool 才 100 多行,很轻量
java 转的 golang ,以前写 java 和 c#
你用 java 多久了?
上家公司用 java , spring mvc 什么的。在那里工作了 7 个月。之前在学校也有做过。
😓还是多去看看吧
有话就说,吞吞吐吐的真是烦
你以为你谁啊。没兴趣义务多说。 sb
大家都是做技术的,说话直来直去就行了,如果您觉得我哪里说得不对的就直说,没想明白怎么说就闭嘴。不用您费心回复这三条。
还有楼上这位,不知道我的主题哪句话戳到您可怜的玻璃自尊心了,让您感觉我在装逼。手动呵呵。
以前感觉在 v2 的都是同行,姿势水平都是比较高一些的人,没想到也能碰上这种垃圾。
两位我已 block 。早上刚上班说话比较冲,如果您二位感觉有啥不爽的,您就憋着吧。
最后 at 一下站长,这种直接说脏话的,应该封号的吧。
在Golang(Go语言)项目中,关于线程池里应放置多少线程的问题,实际上更多关联于Goroutine的调度与系统的资源利用,因为Go语言运行时本身已经很好地抽象了线程管理,通过Goroutine和M(机器线程)、P(处理器)的调度模型实现了高效的并发。
-
系统资源限制:首先应考虑的是系统资源,包括CPU核心数、内存以及I/O性能。一般来说,理想的Goroutine数量可以略多于CPU核心数,以便充分利用多核优势并保持一定的上下文切换开销。
-
任务性质:任务的计算密集度与I/O密集度决定了Goroutine的最优数量。对于计算密集型任务,Goroutine数量接近CPU核心数通常较优;而对于I/O密集型任务,由于I/O等待会释放处理器,可以配置更多的Goroutine来保持CPU的忙碌。
-
动态调整:在实际应用中,很难静态确定最优Goroutine数量。可以考虑使用监控工具观察系统的资源使用情况,如CPU利用率、内存占用等,并根据应用性能进行动态调整。
-
Go运行时优化:Go的运行时已经为Goroutine的调度做了大量优化,通常不需要开发者过多干预。除非有明确的性能瓶颈,否则可以信任Go的运行时调度器来做出合理决策。
综上所述,线程池(在Go中更多表现为Goroutine池)的大小应根据实际系统资源、任务特性及运行时表现综合考量,灵活调整以达到最佳性能。