查看原文
其他

如何确定系统的最佳线程数?

编程一生 编程一生 2024-02-26

确定系统的最佳线程数属于衡量容量的范畴,根据上期的知识点。衡量容量就要用到压测和监控。

确定系统的最佳线程数大体上分三步:第一步,分析理论值;第二步,用压测进行调整获得实际值;第三步,持续监控,观察是否需要再次调整。

理论值,首先分析资源。Linux操作系统有进程允许的最大线程数限制,默认是1024,当然这个是可以改的,还有文件句柄等其他资源,一般都不是瓶颈。每个Java线程都要占用内存空间。栈空间默认是1M,可通过JVM参数调整。

与线程数关联最紧密的是CPU资源。IO密集型服务和CPU密集型服务的线程数差异很大。在《java并发编程实践》中,建议对于CPU密集型,设置为CPU核数+1;对于IO密集型,有个公式:
线程数= CPU的数量*目标CPU使用率* (1 + 等待时间/计算时间的比率)。

咱们先来根据实际情况计算一个场景,比如第三方支付的场景,使用4核8G虚拟机,目标CPU使用率为90%,发起请求调用,内部处理耗时2ms,剩下的时间等待下游支付通道返回结果,耗时200ms。那计算出来,线程数为360。

实际值,还拿刚才的场景做压测,以360为基准进行调整,观察在TPS300以下,CPU使用率是成线性增长的,线程数多些少些并不影响。压到300以上,压不上去了,因为瓶颈不在应用程序上,而是受限于其他依赖方。常见的是数据库。

所以实际工作中,见到最大线程数设置的很大,比如1000,好像也没什么问题。因为瓶颈不在这里了。但实际支持最大并发也就200,根本不会有1000个线程真的在用,设置大些只要系统资源充足,可以防止线程池被打满。相反,如果系统资源不充足,或者有明确的并发上限,线程数按照压测并发上限来设置可以起到限流保护的作用。

持续监控,可以使用jstack观察是否有较多的等待获取任务的线程,这意味着资源允许的条件下可增加线程来提高并发量。赶上双十一大促,咱就不要登录机器操作这些危险命令了,老老实实看可视化监控吧。

思考1:有同学在想,线程数设置很大,相应不会造成大量上下文切换,影响性能吗?

对于IO密集型系统来说,流程主要是在做外部调用,内部需要CPU连续处理实际花费时间是毫秒以下。所以本来也就该进行CPU切换来释放CPU,等待IO操作了。所以很多人设置最大线程数随便设置了一个很大的数值,好像也没什么问题。实际上,嗯,可能真没什么问题。

思考2:一个时间片可以做多少事儿?

我们按照CPU主频2GHZ来计算,一个CPU时间片按1ms计算(实际一般更长一些),假设:均一个操作指令是2个时周期,2GHZ主频的CPU的时钟周期为0.5ns,也就是说一个时间片可以执行百万条指令。

假设咱们一个IO密集型接口程序逻辑时间复杂度是O(n),有2百行代码组成,输入数据一次批量10条,也就是展开执行2千行代码,假设1行代码需要执行10个指令(一般用不了),也就万个指令级别。一个时间片搞得定。

继续滑动看下一个

如何确定系统的最佳线程数?

编程一生 编程一生
向上滑动看下一个

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存