Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/320.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么增加线程数是无用的?_Java_Multithreading_Rabbitmq - Fatal编程技术网

Java 为什么增加线程数是无用的?

Java 为什么增加线程数是无用的?,java,multithreading,rabbitmq,Java,Multithreading,Rabbitmq,我一直在寻找提高处理从rabbitmq队列接收的消息的速度的方法。我发现的唯一方法是让多个线程执行相同的操作——接收和处理。这给了我一些利润。在我创建了4个线程之后,速度提高了四倍。由于我有8核处理器,我决定将线程数增加到8。但这并没有提高性能。YourKit显示只有50%的CPU被使用。有人会说我的应用程序是轻量级的,所以它是如此,但我可以说,它不能做更多的工作比它做什么,无论我产生更多的做什么。为什么这不起作用?有许多不同的问题会限制给定系统上某些应用程序的最大速度。例如,它可能受到内存带宽

我一直在寻找提高处理从rabbitmq队列接收的消息的速度的方法。我发现的唯一方法是让多个线程执行相同的操作——接收和处理。这给了我一些利润。在我创建了4个线程之后,速度提高了四倍。由于我有8核处理器,我决定将线程数增加到8。但这并没有提高性能。YourKit显示只有50%的CPU被使用。有人会说我的应用程序是轻量级的,所以它是如此,但我可以说,它不能做更多的工作比它做什么,无论我产生更多的做什么。为什么这不起作用?

有许多不同的问题会限制给定系统上某些应用程序的最大速度。例如,它可能受到内存带宽、非并行代码所需时间(包括同步块、I/O带宽和缓存空间)的限制


如果您想要进一步的改进,您需要进行一些测量和分析,以找到时间的方向,然后再进行处理。

在给定的系统上,有许多不同的问题可能会限制某些应用程序的最大速度。例如,它可能受到内存带宽、非并行代码所需时间(包括同步块、I/O带宽和缓存空间)的限制


如果您想要进一步的改进,您需要进行一些测量和分析,以找到时间的方向,然后着手解决这个问题。

简短而没有特别帮助的答案是开销和瓶颈

例如:

用Java创建线程的成本相对较高。如果一个线程完成的工作量不大,那么创建线程的开销可能会超过它的好处

线程之间的上下文切换相对昂贵,特别是考虑到与内存相关的开销时,如缓存未命中、TLB未命中。当将本机线程分配给核心时,这些开销实际上会受到影响。如果操作系统能够以某种方式将一个本机线程连续地保留在一个内核上,即在同一个内核上没有其他线程,那么它可以使用自旋锁。。。并避免上下文切换。但是Java线程越多,操作系统就越不可能做到这一点

线程可能会花费大量时间等待I/O完成。I/O系统的吞吐量或某些外部服务的速度/延迟可能是一个瓶颈

您可能对数据结构存在争用;e、 需要独占访问才能安全读取或更新的线程称为共享映射。如果线程经常需要等待其他线程释放锁,那么就会出现瓶颈

您的计算可能主要取决于为线程提供数据的成本。例如,如果有一个主线程将工作分配给工作线程,那么主线程的活动可能是瓶颈;i、 它可能无法提供足够的工作让工人们忙碌

因为您的标记暗示您正在使用消息队列,所以这可能是瓶颈,特别是当消息很大或对每个消息所做的工作相对较小时

使用单独的消息队列服务可能会增加上下文切换、增加I/O延迟、增加协议开销等。对于小规模系统来说,这不是一条自动提高性能的途径


也可能是您的内核被超线程化了,而不是真正的内核,或者操作系统正在阻止您的JVM使用所有的内核。

简短且没有特别有用的答案是开销和瓶颈

例如:

用Java创建线程的成本相对较高。如果一个线程完成的工作量不大,那么创建线程的开销可能会超过它的好处

线程之间的上下文切换相对昂贵,特别是考虑到与内存相关的开销时,如缓存未命中、TLB未命中。当将本机线程分配给核心时,这些开销实际上会受到影响。如果操作系统能够以某种方式将一个本机线程连续地保留在一个内核上,即在同一个内核上没有其他线程,那么它可以使用自旋锁。。。并避免上下文切换。但是Java线程越多,操作系统就越不可能做到这一点

线程可能会花费大量时间等待I/O完成。I/O系统的吞吐量或某些外部服务的速度/延迟可能是一个瓶颈

您可能对数据结构存在争用;e、 需要独占访问才能安全读取或更新的线程称为共享映射。如果线程经常需要等待其他线程释放锁,那么就会出现瓶颈

您的计算可能主要取决于为线程提供数据的成本。例如,如果有一个主线程将工作分配给工作线程,那么主线程的活动可以是bo 颈;i、 它可能无法提供足够的工作让工人们忙碌

因为您的标记暗示您正在使用消息队列,所以这可能是瓶颈,特别是当消息很大或对每个消息所做的工作相对较小时

使用单独的消息队列服务可能会增加上下文切换、增加I/O延迟、增加协议开销等。对于小规模系统来说,这不是一条自动提高性能的途径


也有可能是因为您的超线程内核不是真正的内核,或者操作系统正在阻止JVM使用所有内核。

如果CPU或等待IO是您的瓶颈,那么添加独立线程可以带来很大的不同

如果共享资源是一个瓶颈,例如L3缓存、网络适配器、内核,那么添加线程将无济于事,因为CPU不是问题所在。事实上,增加开销往往会使情况变得更糟

我的应用程序是轻量级的


在这种情况下,CPU不太可能是您的问题,您很高兴看到一个以上的CPU加速。很可能您正在加速RabbitMQ使用的CPU。理想情况下,它应该更有效,这应该没有多大帮助。依我看,多个CPU不会给更高效的消息传递解决方案带来太多好处,因为它们不会成为CPU的瓶颈。

如果CPU或等待IO是您的瓶颈,那么添加独立线程可以带来很大的不同

如果共享资源是一个瓶颈,例如L3缓存、网络适配器、内核,那么添加线程将无济于事,因为CPU不是问题所在。事实上,增加开销往往会使情况变得更糟

我的应用程序是轻量级的


在这种情况下,CPU不太可能是您的问题,您很高兴看到一个以上的CPU加速。很可能您正在加速RabbitMQ使用的CPU。理想情况下,它应该更有效,这应该没有多大帮助。恕我直言,多个CPU不会给更高效的消息传递解决方案带来太多好处,因为它们不会受到CPU瓶颈的限制。

无论如何,您只使用了4个内核。有很多东西可以阻止你通过加倍线程来加倍性能,但是从你4线程的成功中,你已经克服了这一切。我猜在你的代码中有一个bug,它触发了8个线程,但只触发了4个。即使是超读,你也会得到一些改善。即使有每一个可能的问题,你也会得到一些改进。否则,我会选择T.J.Crowder和Stephen C:我不认为你真的有8个核

我会尝试使用不同数量的线程:3、5、6。看看有什么变化。我想你很快就会发现这个问题的


公平地说,Java:如果您编写线程安全代码并避免瓶颈,那么它可以很好地处理线程,正如您所注意到的,从一个线程到4个线程。我总是发现开销很小。

不管怎样,您只使用了4个内核。有很多东西可以阻止你通过加倍线程来加倍性能,但是从你4线程的成功中,你已经克服了这一切。我猜在你的代码中有一个bug,它触发了8个线程,但只触发了4个。即使是超读,你也会得到一些改善。即使有每一个可能的问题,你也会得到一些改进。否则,我会选择T.J.Crowder和Stephen C:我不认为你真的有8个核

我会尝试使用不同数量的线程:3、5、6。看看有什么变化。我想你很快就会发现这个问题的


公平地说,Java:如果您编写线程安全代码并避免瓶颈,那么它可以很好地处理线程,正如您所注意到的,从一个线程到4个线程。我总是发现开销很小。

您的应用程序没有线性加速,因此没有良好的可扩展性

为了保持线程数量的增加,您需要确保正在处理的数据相应地增加。对于固定数量的数据,增加线程和/或内核的数量将在某个时候产生递减的回报,因为创建线程的开销将超过线程的计算时间

确保查找以下链接:


Gustafson定律是Ahmdal定律的一个很好的对比,因此我强烈建议您理解这篇文章。

您的应用程序没有线性加速,因此,它没有良好的可扩展性

为了保持线程数量的增加,您需要确保正在处理的数据相应地增加。对于固定数量的数据,增加线程和/或内核的数量将在某个时候产生递减的回报,因为创建线程的开销将超过线程的计算时间

确保查找以下链接:

古斯塔夫森定律与艾哈迈德定律是一个很好的对比,所以我强烈推荐understan

读那篇文章。

当您达到50%的CPU负载时,队列中还有主题吗?也许你没有向队列发送足够的主题,或者我现在在其他地方遇到的瓶颈。你的算法中可能有一个序列化部分,使得线程数量的增加毫无结果。你说你有一个8核CPU。你确定那是真的吗?或者它真的是一个具有超线程的4核CPU?对于很多工具来说,这些看起来像8核CPU,但超线程实际上并没有为您提供额外的内核,只是提供了更快的上下文切换。当您收到消息时,您在做什么?队列中备份了多少邮件?您是否使用了会大大降低性能的事务性消息D、 用CPU运行太多线程就像灾难一样,特别是当线程彼此同步时,当您达到CPU负载的50%时,队列中还有主题吗?也许你没有向队列发送足够的主题,或者我现在在其他地方遇到的瓶颈。你的算法中可能有一个序列化部分,使得线程数量的增加毫无结果。你说你有一个8核CPU。你确定那是真的吗?或者它真的是一个具有超线程的4核CPU?对于很多工具来说,这些看起来像8核CPU,但超线程实际上并没有为您提供额外的内核,只是提供了更快的上下文切换。当您收到消息时,您在做什么?队列中备份了多少邮件?您是否使用了会大大降低性能的事务性消息D、 用CPU运行太多线程就像灾难一样,特别是当线程彼此同步时。你知道,当我查看探查器时,我发现只有50%的CPU用于4个线程或8个线程。核心的数量不是来自于此吗?@NikitinMikhail:可能吧。您似乎遇到了困难,而典型的线程性能问题更为严重,一次只运行一个线程,或者更不严重,例如,您的8个线程只提供60-80%的CPU,而不是100%。我只看到两个答案。要么你的代码中有一个bug,只运行4个线程而不是8个线程,要么你只有4个工作内核。即使是糟糕的超热疗也会让你的血压超过50%。如果三个线程使用更少的CPU,但5和6什么也不做,那么这就是核心。如果你意识到你在使用8的时候使用了4,那么这就是一个bug。@NikitinMikhail:关键是那堵砖墙。查看其他答案,虽然他们解释了速度减慢,但他们没有解释。你知道,当我查看分析器时,我发现只有50%的CPU用于4个线程或8个线程。核心的数量不是来自于此吗?@NikitinMikhail:可能吧。您似乎遇到了困难,而典型的线程性能问题更为严重,一次只运行一个线程,或者更不严重,例如,您的8个线程只提供60-80%的CPU,而不是100%。我只看到两个答案。要么你的代码中有一个bug,只运行4个线程而不是8个线程,要么你只有4个工作内核。即使是糟糕的超热疗也会让你的血压超过50%。如果三个线程使用更少的CPU,但5和6什么也不做,那么这就是核心。如果你意识到你在使用8的时候使用了4,那么这就是一个bug。@NikitinMikhail:关键是那堵砖墙。看看其他的答案,虽然他们解释了慢下来,但他们没有解释。我很难从你的答案中找到对我的意义。我是舒尔,CPU是瓶颈。当我只有一个消耗线程时,你的工具包显示只有13-16%的CPU被使用。在我将其增加到4个线程后,该值更改为40-50%。生产者可以生成更多的消息,但由于消费者不快速发送确认,因此无法发送更多消息。我是舒尔,rabbitmq服务器可以发送高达2000 mesgs/s的数据。考虑到我的MSG的大小,我同意接受1000甚至800,但不是400-450@NikitinMikhail空闲CPU并不表示添加更多CPU会有所帮助。它只表示您可以添加更多线程。如果瓶颈是L3缓存,或者每个线程上产生的CPU使用量将达到最大值,但吞吐量不会增加,但延迟通常会增加,而RabbitMQ可能每秒执行2000个消息,这通常不包括写入或读取这些消息之类的任何其他内容,他们通常测试/引用未触及的字节[]。我很难从你的答案中找到我的意思。我是舒尔,CPU是瓶颈。当我只有一个消耗线程时,你的工具包显示只有13-16%的CPU被使用。在我将其增加到4个线程后,该值更改为40-50%。生产者可以生成更多的消息,但由于消费者不快速发送确认,因此无法发送更多消息。我是舒尔,rabbitmq服务器可以发送高达2000 mesgs/s的数据。考虑到我的MSG的大小,我同意接受1000甚至800,但不是400-450@NikitinMikhail空闲的CPU不起作用 表示添加更多CPU将有所帮助。它只表示您可以添加更多线程。如果瓶颈是L3缓存,或者每个线程上产生的CPU使用量将达到最大值,但吞吐量不会增加,但延迟通常会增加,而RabbitMQ可能每秒执行2000个消息,这通常不包括写入或读取这些消息之类的任何其他内容,它们通常测试/引用未触及的字节[]。