巴特先生和寻找正确的线程配置文件


有时候(比我们想象的更频繁),并发性越少实际上越多。不久前,我发现自己在一次对话中讨论了无阻塞架构、调优和性能。我们讨论了这些模型的调优通常从“2threads每内核”(2TB)。这场讨论让我好奇Mule如果由2TPC测试,美国的批处理模块将会运行。我事先就知道2PC在批量生产时不会让人印象深刻,主要是因为它不使用无阻塞threading模特。然而,我发现自己认为16线程是默认的threadingprofile可能有点过分(同样,因为有时少就是多),想看看如果我们尝试它会发生什么。你知道,只是出于好奇。

设计测试

我向强者解释了我的假设Luciano Gandini来自我们的表演团队。他指出,有两种不同的情况需要测试:

  • 主要是IO绑定,它们花费大部分执行时间来执行IO操作(磁盘、数据库、外部APIs等等)
  • 主要受中央处理器限制的作业。他们也可以做大量的输入输出,但是大部分的处理时间都花在了中央处理器操作上(转换、验证等)。

问题:因为批处理依赖于持久队列来支持大数据集,同时保证可靠性和弹性,所以没有批处理作业真正依赖于输入输出。然而,因为无论你使用多少线程,这个事实的影响都是相似的,所以为了这个测试的目的(也仅仅是为了这个目的),我们可以假设这个因素不存在。

卢西亚诺随后设计了两个batch jobs一个是输入输出密集型,一个是中央处理器密集型。每个作业都用100万条记录数据集执行了几次。测试是在一台24核的计算机上进行的(表演人员有非常棒的玩具!)并且在每次运行中使用不同的线程配置文件。结果如下:

输入输出绑定作业

前两次运行使用了8个和16个线程,后一次运行要快得多。这很容易解释——因为在输入输出上工作很难,许多线程会发现自己被锁定,等待输入输出操作完成。通过添加更多线程,您可以进行更多工作。然后,第三次运行使用了24个线程(每个内核一个)。同样,这是更快,但不是很多。再说一次,这并不奇怪。尽管有更多的工作要做,新线程也在基本相同的时间阻塞输入输出操作,同时增加了对上下文切换和线程管理的惩罚。最后一次运行使用了48个线程(真正的2TB),尽管速度更快,但与额外的中央处理器和内存成本相比,改进并不显著。

结论:更多的线程确实提高了性能,但只是在一定程度上,你会发现这相当快。默认的16个线程已经过验证。

明白了:如果你工作的输入输出包括消耗外部API,添加更多线程可能比这里显示的更有害。这是因为有些应用编程接口在一天可以执行多少调用,甚至可以同时执行多少调用方面是有限制的。超过这些阈值可能会导致您的请求被拒绝或限制。

受中央处理器限制的作业

这些结果确实出人意料。首先,因为这种行为与输入输出绑定作业的行为非常相似,所以这两种情况不同的第一个假设是第一个被测试推翻的。

对于前两次运行8和16个线程,结果是相似的。16个线程在不到一半的时间内完成了这项工作。然而,最大的不同是,24和48次跑的时间几乎相同。这是因为该作业上的线程根本没有花费任何时间被输入输出操作阻塞,所以添加线程的开销几乎消耗了所有获得的处理能力。不得不承认,我没想到会这样。

结论:无论工作性质如何,行为都非常相似。尽管对于CPU密集型应用,一旦超过16个线程的界限,这种衰减会更加明显。16个线程的默认值再次得到验证。

最后的想法

好消息是,看起来我们不需要批量更改任何默认值。但最重要的是,结果提供了一些我们没有预料到的关于调优和性能的经验。但是请记住,没有两种工作是天生相似的。你也可能有不遵循这些趋势的案例。这篇文章的目的不是告诉你该做什么,而是给你一些关于如何测试你正在做什么的想法。希望在这方面有所帮助。

我们非常希望您能分享您的批处理作业类型,以及它们对线程配置文件变化的反应。期待验证这些趋势或获得更多惊喜!

干杯。