这篇文章源于我们在项目中使用线程池时,但是不会评估线程池的一些初始参数应该怎么设置。我们的服务是部署在公司的私有云平台 上,一共申请了4个节点,每个节点是一个docker,每个节点的配置是4核8G,一般书籍或者网上的博客都指出:对于IO密集型应用,线程池的大小应该设置为 2*N + 1;CPU密集型的应用,线程池的大小设置为N + 1,其中N是CPU核数。

  问题:我一开始认为我们单节点只有4核,我以为这样你最多也只能起4个线程同时执行某个任务,线程池大小设置得再大也没什么用, 这是背景,这里怪自己太懒惰了,也没有自己写个程序去尝试跑一下,看能最多起多少个线程出来。

  现在我们来重新理解一下Linux系统的CPU核的几个概念:

1、物理CPU数量

  物理CPU指的是实际服务器中插槽上的CPU个数,也就是不重复的physical id 有几个,可以通过下面命令看到:

  grep ‘physical id’ /proc/cpuinfo | sort -u

  这个命令输出的就是你的物理CPU数目,可以看到是2个。在公司私有云的4核节点上,10核的节点上,输出都是如下:

  physical id : 0

  physical id : 1

2、每颗物理CPU的核数

  每颗物理CPU的核数指的就是:一块CPU上能处理数据的芯片组的数量,可以通过下面命令查看

  grep ‘core id’ /proc/cpuinfo | sort -u | wc -l

  这个命令输出每个物理CPU的核数,在我们4核服务器上输出的是10,和上面结合,那就是

  总核数 = 物理CPU数目 * 每颗物理CPU的核数 = 2 * 10 = 20。这是我们单节点的总核数。

3、逻辑CPU数目

  一般情况下,一个CPU有多核,再加上超线程技术,可以在逻辑上再分出一倍的核数,可以通过下面命令查看

  grep ‘processor’ /proc/cpuinfo | sort -u | wc -l

  在我们的4核服务器上,这个值的输出是40,因为现在服务器都默认启用了超线程技术,即:

  总逻辑CPU数 = 物理CPU数目 * 每颗物理CPU的核数 * 超线程数 = 2 * 10 * 2 = 40。

  超线程技术:超线程技术是在一颗CPU同时执行多个程序而共同分享一颗CPU内的资源,理论上要像两颗CPU一样在同一时间执行两个 线程,虽然采用超线程技术能同时执行两个线程,但它并不象两个真正的CPU那样,每个CPU都具有独立的资源。当两个线程都同时需要 某一个资源时,其中一个要暂时停止,并让出资源,直到这些资源闲置后才能继续。因此超线程的性能并不等于两颗CPU的性能。

  todo:通过上面命令可以看到,公司私有云平台上分配的4核节点和10核节点,区别仅在于4核节点,每颗物理CPU的核数是10个, 而10和核节点上,每颗物理CPU的核数是12个,这么一看,似乎区别并不大?