简体   繁体   English

为什么我的Java长时间运行的线程(5k +线程)没有利用所有机器内核(12个内核)?

[英]Why my java long running Threads (5k+ thread) not utilizing all machines cores (12 cores)?

I've Worte a simple multithread java application, The main method just creates 5k threads, each thread will loop over a list having 5M records to process. 我已经编写了一个简单的多线程Java应用程序,main方法仅创建5k个线程,每个线程将循环遍历要处理的5M条记录的列表。

My Machine specs: 我的机器规格:

  • CPU cores: 12 cores CPU核心:12核心
  • Memory: 13Gb RAM 内存:13Gb RAM
  • OS: Debian 64-bit 操作系统:Debian 64-bit

My jar is now running, And I use hTop to monitor my application and this is what I can see while its running 我的jar现在正在运行,并且我使用hTop监视我的应用程序,这是我在运行时可以看到的内容

在此处输入图片说明

And This is how I construct a Thread: 这就是我构造线程的方式:

ExecutorService executor = Executors.newCachedThreadPool();
Future<MatchResult> future = executor.submit(() -> {
            Match match = new Match();
            return match.find(this);
        });

Match.class 匹配类

find(Main main){
// looping over a list of 5M 
// process this values and doing some calculations 
// send the result back to the caller 
// this function has no problem and it just takes a long time to run (~160 min)
}

And now I have some questions: 现在我有一些问题:

1- Based on my understanding if I have a multiThreaded process, it'll fully utilize all my cores until the task is completed, so why the work load is only around 0.5 (only half a core is used)? 1-根据我的理解,如果我有一个多线程进程,它将充分利用我的所有内核,直到任务完成为止,那么为什么工作量仅为0.5(仅使用一半内核)?

2- Why my Java app state is "S" (sleeping) while its actually running and filling up the logs file? 2-为什么我的Java应用程序实际运行并填充日志文件时,其状态为“ S”(睡眠)?

3- Why I can only see 2037 threads out of 5k are running (this number was actually less than this and its getting increased over time) 3-为什么我只能看到5k中有2037个线程正在运行(这个数目实际上少于这个数目,并且随着时间的推移而增加)

My Target: to utilize all cores and get all this 5k+ done as fast as it can be :) 我的目标:利用所有内核,并尽快完成所有5k +的工作:)

Based on my understanding if I have a multiThreaded process, it'll fully utilize all my cores until the task is completed. 根据我的理解,如果我有一个多线程进程,它将充分利用我的所有内核,直到任务完成。

Your understanding is not correct. 您的理解不正确。 There are lots of reasons why cores may not (all) be used in a poorly designed multi-threaded application. 有很多原因可能导致内核不能(全部)用于设计不良的多线程应用程序中。

so why the work load is only around 0.5 (only half a core is used)? 那么为什么工作量仅约为0.5(仅使用半个核心)?

A number of possible reasons: 多种可能的原因:

  1. The threads may be deadlocked. 线程可能会死锁。
  2. The threads may all be contending for a single lock (or a small number of locks), resulting in most of them waiting. 线程可能都争用一个锁(或少量锁),从而导致大多数等待。
  3. The threads could all be waiting for I/O; 线程可能都在等待I / O。 eg reading the records from some database. 例如从某个数据库中读取记录。

And those are just some of the more obvious possible reasons. 这些只是一些更明显的可能原因。

Given the that your threads are making some progress, I think that explanation #2 is a good fit to your "symptoms". 考虑到您的线程正在取得一些进展,我认为解释#2非常适合您的“症状”。


For what it is worth, creating 5k threads is almost certainly a really bad idea. 就其价值而言,创建5k线程几乎肯定是一个非常糟糕的主意。 At most 12 of those could possibly be running at any time. 其中最多可以随时运行12个。 The rest will waiting to run (assuming you resolve the problem that is leading to thread starvation) and tying down memory. 其余的将等待运行(假设您已解决了导致线程饥饿的问题)并占用了内存。 The latter has various secondary performance effects. 后者具有各种次要性能效果。

My Target: to utilize all cores and get all this 5k+ done as fast as it can be :) 我的目标:利用所有内核,并尽快完成所有5k +的工作:)

Those two goals are probably mutually exclusive :-) 这两个目标可能是互斥的 :-)


All threads are logging to the same file by a the java.util.Logger. 所有线程都通过java.util.Logger记录到同一文件。

That is a possibly leading to them all contending for the same lock ... on a something in the logger framework. 这可能导致他们都争相在记录器框架中的某事物上锁定相同的锁。 Or bottlenecking on file I/O for the log file. 或日志文件的文件I / O出现瓶颈。

Generally speaking logging is expensive. 一般来说,日志记录很昂贵。 If you want performance, minimize your logging, and for cases where the logging is essential, use a logging framework that doen't introduce a concurrency bottleneck. 如果要提高性能,请尽量减少日志记录,对于必须进行日志记录的情况,请使用不会引入并发瓶颈的日志记录框架。


The best way to solve this problem is to profile the code and figure ouot where it is spending most of its time. 解决此问题的最佳方法是分析代码并确定其大部分时间在哪里。

Guesswork is inefficient. 猜测工作效率低下。

Thank you guys, I've fixed the problem and now Im having the 12 cores running up to maximum as you see in the picture. 谢谢大家,我已经解决了这个问题,现在我可以使12核达到最大,如图所示。 :) :)

在此处输入图片说明

I actually tried to run this command jstack <Pid> to see the status of my all running threads in this process ID, and I found that 95% of my threads are actually BLOCKED at the logging line, I did some googling and found that I can use AsynchAppender in log4J so logging will not block the thread 我实际上尝试运行此命令jstack <Pid>来查看此进程ID中所有正在运行的线程的状态,我发现95%的线程实际上在logging行处被阻塞,我进行了一些谷歌搜索,发现我可以在log4J中使用AsynchAppender,因此日志记录不会阻塞线程

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM