以下摘自Java Concurrency in Practice,第12.2章性能测试,其中作者讨论了有界缓冲区实现的吞吐量。
图12.1显示了使用缓冲区的4路机器上的一些示例结果 容量为1,10,100和1000.我们立即看到一个缓冲区 一个大小导致非常差的吞吐量;这是因为每个线程 在阻止和等待之前只能做一点点进步 另一个线程。将缓冲区大小增加到10会有很大帮助,但是 增加过去十年提供的收益递减。
首先添加更多线程可能有点令人费解 仅略微降低性能。原因很难从中看到 数据,但在CPU性能表上很容易看到,比如perfbar 测试正在运行:即使有很多线程,也没有多少计算 继续,其中大部分用于阻塞和解锁线程。所以 有足够的CPU冗余让更多的线程做同样的事情 没有太大的伤害性能。
但是,请注意从这些数据中得出结论 总是向使用a的生产者 - 消费者程序添加更多线程 有界缓冲区。这个测试在模拟方面是相当人为的 应用;生产者几乎没有工作来生成该项目 放在队列中,消费者几乎不与该项目一起工作 检索。如果工作者在一个真正的生产者 - 消费者中穿线 应用程序做一些非常重要的工作来生产和消费物品(如 一般情况下),然后这个松弛就会消失而且 有太多线程的影响可能非常明显。该 这个测试的主要目的是衡量什么约束 通过有界缓冲区进行的生产者 - 消费者切换总体上强加了 吞吐量。
作者对 cpu slack 的意思是什么?随着更多线程的添加,为什么吞吐量降低不会越来越低?我没有按照作者给出的关于轻微性能下降的原因,同时添加越来越多的线程,假设缓冲区大小的界限保持不变。
编辑:我可以想到一个原因:因为在这种情况下线程没有真正的工作,所以共享内存总线上流量增加的经典问题,由于缓存未命中的数量随着越来越多的线程被添加,线程的上下文切换不起主要作用。一旦线程开始做更多工作,情况就会改变。这是作者在第三段中试图传达的内容吗?
答案 0 :(得分:1)
没有像CPU松弛这样的正式术语。作者只是意味着CPU没有完全用于做有意义的工作,因为大部分时间都花在等待成功获得互斥锁上。作者正在调用CPU的未使用容量,CPU松弛。
注意:相关代码测试多个生产者/多个消费者场景,生产者和消费者数量相等。
编辑:在后面的讨论中,他们讨论了添加更多线程的效果,如果a)线程几乎不起作用,并且b)线程基本上为每个生产或消费的项目占用CPU。我将尝试用一些有点人为的场景解释这些差异。
假设锁定主动占用1个时间单位,等待8个时间单位被动。被动等待不会占用CPU。
案例1:生产者 - 消费者成本是1个时间单位。
所以我们目前占用2个时间单位的CPU时间,用 额外的8个时间单位的被动等待时间。所以我们有8/10 可用的CPU时间单位。
如果我们现在想要将线程数加倍,我们需要适应 另外2个时间单位(1个用于生产者 - 消费者,1个用于 主动锁定时间)。这会影响我们可用的CPU供应量 时间 - 但我们已经足够了。
案例2:生产者 - 消费者成本是11个时间单位。
因此,我们目前占用了11 + 1 = 12个时间单位的CPU时间,另外还有8个时间单位的被动等待时间。所以我们有8/20个可用的CPU时间单位。
如果我们现在想要将线程数加倍,我们需要额外容纳12个时间单位(11个用于生产者 - 消费者,1个用于主动锁定时间)。这超出了可用的CPU时间单位。必须要付出代价 - 所以等待时间会增加,吞吐量会受到影响。
因此,在案例2中,实际工作量减少了新线程的可用时间,从而增加了锁定争用对吞吐量的观察效果。如果他们在本书中也包含了这个想象场景的数字,那就太好了。这将使他们的手工波浪论点更容易理解。
答案 1 :(得分:-1)
我认为cpu slack是资源。根据维基百科的说法,如果现在就开始工作,则会提到工作后剩余的时间。 大量的cpu冗余意味着很多计算资源。当消费者/生产者做一些非常重要的事情时,cpu松弛减少并影响吞吐量。