前言:线程池可以包含几个线程才能最大化提升整体系统性能,这个与CPU的处理能力有直接关系,线程池的线程数过多则在大多数线程处于等待状态,线程之间的切换反而性能开销变大,拖累整体效率,如果线程池里的线程过小,则没有充分利用CPU的处理能力。
一、查看CPU并发处理的线程数
在Linux环境中,使用lscpu命令,效果如下
-
CPU架构与操作模式:
-
Architecture: x86_64,表明这是一个64位的CPU架构,支持32位和64位的操作模式。
-
-
CPU核心数与线程数:
-
(1) CPU(s): 8,表示系统中有8个逻辑CPU。但这里需要注意,逻辑CPU数量并不直接等同于物理核心数或线程数,它可能受到超线程技术的影响。
-
(2) Thread(s) per core: 1,明确指出每个核心只有一个线程。这意味着该CPU没有启用超线程技术,每个物理核心仅支持一个线程。
-
(3) Core(s) per socket: 4,表示每个CPU插槽(或物理CPU)有4个核心。
-
(4) 座:2,表明系统中有两个CPU插槽,每个插槽可能插入了一个CPU。
-
一般来说,逻辑CPU数的计算公式可以表示为:
-
逻辑CPU数 = CPU插槽数(座数) × 每个插槽的物理核心数(Core(s) per socket) × 每个核心的线程数(Thread(s) per core);
-
-
计算总线程数:
-
既然每个核心只有一个线程,且每个CPU插槽有4个核心,系统中有2个CPU插槽,那么总的核心数就是 4 * 2*1 = 8。
-
由于每个核心只支持一个线程,因此总的线程数也等于核心数,即8个线程。
-
-
结论:
-
基于以上分析,该CPU可以支持8个线程的并发执行。由于未启用超线程技术,每个物理核心仅运行一个线程。
-
二、线程池大小和CPU的瓶颈
1. 确定任务性质
-
CPU密集型任务:如果任务主要是计算密集型,且计算量较大,那么线程池的大小应该设置为等于或略小于CPU核心数。这是因为过多的线程会导致频繁的上下文切换,从而降低性能。
-
I/O密集型任务:如果任务涉及大量的I/O操作(如数据库访问、文件读写、网络请求等),那么线程池可以设置得更大一些,因为线程在等待I/O操作完成时可以被其他线程使用。
-
都不密集型任务:CPU利用率和内存利用率等都不是很高,这种系统的特点就是虽然计算的数据或者网络交互次数虽然多,但是每次计算或者交互的时间都比较短,在数据量大的情况下只是执行的时间较长,并没有引起CPU或者I/O的利用率飙升。
对于都不密集型情况如果单纯的增加线程往往并不能解决性能问题,例如,8核(逻辑)CPU在理论上,如果定位是I/O密集型任务,网上推荐的线程数是2N+1,即17个,但一个线程的完成一次的任务时间较快,且没有引起I/O的异常利用,这时候如果使用16个线程跑自动任务后会发现性能依然下降,且执行的结果来看,最多依然是8个线程同时(从数据落地时间观察)。推理发现了即使任务本身过程中I/O比CPU多,但瓶颈不一定就是I/O,原因是因为I/O的利用率其实不高,CPU的同时处理就是8个线程,过多的线程数导致了CPU的来回切换,从而降低了性能。真正的I/O密集型操作,应该是用在I/O的时间应该远远大于CPU的计算时间,2N+1个线程在操作时才能更有效的利用CPU计算,CPU也不会称为瓶颈,反之线程执行过快,线程数过多都会导致CPU处理成为瓶颈。
2. 监控和调整
在实际应用中,建议通过监控线程池的运行情况(如线程的利用率、任务队列的长度等)来动态调整线程池的大小。这有助于确保系统在高负载下仍然能够保持稳定和高效的运行。
3. 实际例子
8核(逻辑)CPU的环境上同时运行基础数据模块和事件分析模块,目前CPU最大同时支持并发线程处理数是8,为了保证整体系统的稳定,所有自动任务的线程数不超过6,因此基础数据模块和事件分析模块可能会存在同时运行的情况,所以可以平均分配线程并发数为3。如果整体环境硬件比较好,比如支持16核(逻辑)CPU,基础数据模块和事件分析模块可以平均分配线程并发数为6,即风控平台的模块的线程的合理配置一般在【3~6】。
标签:核心,性能,任务,线程,插槽,密集型,CPU From: https://blog.csdn.net/weixin_47259235/article/details/143053454