计算密(CPU)集型的线程恰好在某时因为发生一个页错误或者因其他原因而暂停,刚好有一个“额外”的线程,可以确保在这种情况下CPU周期不会中断工作。
所以对于CPU密集型程序, CPU 核数(逻辑)+ 1 个线程数是比较好的经验值的原因了
I/O密集型程序创建多少个线程合适?上面已经让大家按照图多画几个周期(你可以动手将I/O耗时与CPU耗时比例调大,比如6倍或7倍),这样你就会得到一个结论,对于 I/O 密集型程序:
最佳线程数 = (1/CPU利用率) = 1 + (I/O耗时/CPU耗时)
我这么体贴,当然担心有些同学不理解这个公式,我们将上图的比例手动带入到上面的公式中:
这是一个CPU核心的最佳线程数,如果多个核心,那么 I/O 密集型程序的最佳线程数就是:
最佳线程数 = CPU核心数 * (1/CPU利用率) = CPU核心数 * 1 + (I/O耗时/CPU耗时)
说到这,有些同学可能有疑问了,要计算 I/O 密集型程序,是要知道 CPU 利用率的,如果我不知道这些,那要怎样给出一个初始值呢?
按照上面公式,假如几乎全是 I/O耗时,所以纯理论你就可以说是 2N(N=CPU核数),当然也有说 2N + 1的,(我猜这个 1 也是 backup),没有找到具体的推倒过程,在【并发编程实战-8.2章节】截图在此,大家有兴趣的可以自己看看
理论上来说,理论上来说,理论上来说,这样就能达到 CPU 100% 的利用率
如果理论都好用,那就用不着实践了,也就更不会有调优的事出现了。不过在初始阶段,我们确实可以按照这个理论之作为伪标准, 毕竟差也可能不会差太多,这样调优也会更好一些
谈完理论,咱们说点实际的,公式我看懂了(定性阶段结束),但是我有两个疑问:
我怎么知道具体的 I/O耗时和CPU耗时呢?
怎么查看CPU利用率?
没错,我们需要定量分析了
幸运的是,我们并不是第一个吃螃蟹的仔儿,其实有很多 APM (Application Performance Manager)工具可以帮我们得到准确的数据,学会使用这类工具,也就可以结合理论,在调优的过程得到更优的线程个数了。我这里简单列举几个,具体使用哪一个,具体应用还需要你自己去调研选择,受篇幅限制,暂不展开讨论了
SkyWalking
CAT
zipkin
上面了解了基本的理论知识,那面试有可能问什么?又可能会以怎样的方式提问呢?
面试小问 小问一假设要求一个系统的 TPS(Transaction Per Second 或者 Task Per Second)至少为20,然后假设每个Transaction由一个线程完成,继续假设平均每个线程处理一个Transaction的时间为4s
如何设计线程个数,使得可以在1s内处理完20个Transaction?
但是,但是,这是因为没有考虑到CPU数目。家里又没矿,一般服务器的CPU核数为16或者32,如果有80个线程,那么肯定会带来太多不必要的线程上下文切换开销(希望这句话你可以主动说出来),这就需要调优了,来做到最佳 balance
小问二计算操作需要5ms,DB操作需要 100ms,对于一台 8个CPU的服务器,怎么设置线程数呢?
如果不知道请拿三年级期末考试题重新做(今天晚自习留下来),答案是:
线程数 = 8 * (1 + 100/5) = 168 (个)