赞
踩
我们都知道并发编程能够提高CPU利用率,提高程序执行效率,简言之,很“快”。但是:
看似再问第一句,实则在问第二句。因此并发线程适用场景就是:通过设置正确个数的线程来最⼤化程序的运⾏
速度,就是说能够充分利用CPU和I/O的利用率。下面具体谈谈:
这里提出两个场景:
⼀个完整请求,I/O操作可以在很短时间内完成, CPU还有很多运算要处理,也就是说 CPU 计算的⽐例占很⼤⼀部分
假如我们要计算 1+2+…100亿 的总和,很明显,这就是⼀个 CPU 密集型程序在【单核】CPU下,如果我们创建 4 个线程来分段计算,即:
由于是单核 CPU,所有线程都在等待 CPU 时间⽚。按照理想情况来看,四个线程执⾏的时间总和与⼀个线程5独⾃完成是相等的,实际上还忽略了四个线程上下⽂切换的开销
当然,如果是四核CPU下,
每个线程都有 CPU 来运⾏,并不会发⽣等待 CPU 时间⽚的情况,也没有线程切换的开销。理论情况来看效率提升了 4 倍。
所以,如果是多核CPU 处理 CPU 密集型程序,我们完全可以最⼤化的利⽤ CPU核⼼数,应⽤并发编程来提⾼效率。
与 CPU 密集型程序相对,⼀个完整请求,CPU运算操作完成之后还有很多 I/O
操作要做,也就是说 I/O 操作占⽐很⼤部分
我们都知道在进⾏ I/O 操作时,CPU是空闲状态,所以我们要最⼤化的利⽤ CPU,不能让其是空闲状态
因此,可以得出结论:线程等待时间所占⽐例越⾼,需要越多线程;线程CPU时间所占⽐例越⾼,需要越少线程。
从前面例子我们已经发现,理论上线程数量 = CPU 核数(逻辑)
即可,实际上,数量一般设置为CPU 核数(逻辑)+ 1
.why?看《Java并发编程实战》中说:
计算(CPU)密集型的线程恰好在某时因为发⽣⼀个⻚错误或者因其他原因⽽暂停,刚好有⼀个“额外”的线程,可以确保在这种情况下CPU周期不会中断⼯作。
实际上,当一个线程进行IO阻塞让出CPU给其他线程“瓜分”时,为均分,一般般就是刚好其他线程CPU执行时间能够瓜分IO时间。
最佳线程数 = (1/CPU利⽤率) = 1 + (I/O耗时/CPU耗时)
例如:CPU耗时1,IO耗时6.
最佳线程 = 1 / (1 / 1 + 6) = 1 + 6 = 7 个线程
如果是多核情况,再乘以核数即可
最佳线程数 = CPU核⼼数 * (1/CPU利⽤率) = CPU核⼼数 * (1 + (I/O耗时/CPU耗时))
上述例子如果是4核,则28个线程。
理论上来说,这样就能达到 CPU 100% 的利⽤率如果理论都好⽤,那就⽤不着实践了,也就更不会有调优的事出现了。不过在初始阶段,我们确实可以按照这个理论之作为伪标准, 毕竟差也可能不会差太多,这样调优也会更好⼀些
谈完理论,咱们说点实际的,现在两个疑问:
有几个工具可以得到准确数据:SkyWalking, CAT, zipkin
下面再看几个场景例子:
1.假设要求⼀个系统的 TPS(Transaction Per Second 或者 Task PerSecond)⾄少为20,然后假设每个Transaction由⼀个线程完成,继续假设平均每个线程处理⼀个Transaction的时间为4s.
问:如何设计线程个数,使得可以在1s内处理完20个Transaction?
很简单,平均一个线程处理Transaction是4s,则一个线程每s处理0.25TPS,要求20, 20/0.25 = 80个线程。
但是,这还没有考虑CPU数目,一
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。