跟踪java中的线程冲突

时间:2012-02-20 20:12:11

标签: java performance

使用YourKit,我计量了一个应用程序,并确定了主CPU接收器。我将计算结构化为通过具有固定数量线程的ExecutorService并行化。

在24核计算机上,添加线程的好处非常快4以上。所以,我想,这里肯定会有一些争用或锁定,或IO延迟等等。

好的,我打开了YourKit的'Monitor Usage'功能,并且工作线程中显示的阻塞时间量非常小。通过眼线状态图表,工作线程几乎全部为“绿色”(正在运行),而不是黄色(等待)或红色(被阻止)。

CPU分析仍然显示96%的时间位于工作线程内的调用树中。

所以有些东西正在耗尽实时。可能是调度开销吗?

在伪代码中,您可以将其建模为:

loop over blobs:
    submit tasks for a blob via invokeAll of executor
    do some single-threaded processing on the results
end loop over blobs

在测试运行中,有大约680个blob,以及~13个任务/ blob。因此每个线程(假设四个)每个blob大约发送3次。

硬件:我在我的MacBook pro上小规模地运行测试,然后在一个大胖子戴尔:Linux上的hwinfo报告24个不同的项目--cpu,由

组成
Intel(R) Xeon(R) CPU           X5680  @ 3.33GHz

英特尔的网站告诉我每个都有6个核心,12个线程,我怀疑我有4个核心。

3 个答案:

答案 0 :(得分:2)

假设您有4个核心,每个核心有8个逻辑线程,这意味着您有4个真正的处理单元,可以在32个线程之间共享。它还意味着当你在同一个内核上有2-8个活动线程时,它们必须争夺资源,例如CPU管道和指令和数据缓存。

当您有许多必须等待磁盘或网络IO等外部资源的线程时,这种方法效果最佳。如果你有CPU密集型进程,你可能会发现每个核心一个线程将使用你拥有的所有CPU能力。

我编写了一个库,支持为linux和windows分配线程和内核。如果你有Solaris,它可能很容易移植,因为它支持JNI posix调用和JNA调用。

https://github.com/peter-lawrey/Java-Thread-Affinity

答案 1 :(得分:1)

这很可能不是争用,但如果没有更多细节,很难说。分析结果可能会产生误导,因为Java会在线程或网络I / O上阻止线程报告为RUNNABLE。 Yourkit仍将其视为CPU时间。

最好的办法是打开CPU分析,深入了解工作线程中的时间。如果它主要在java.io类中结束,那么您仍然会遇到磁盘或网络延迟。

答案 2 :(得分:0)

您还没有完全并行化处理。你可能没有提交下一个blob,直到前一个blob的结果完成,因此没有并行处理。

如果可以,请尝试这种方式:

for each blob{

        create a runnable for blob process name it blobProcessor;
        create a runnable for blob results name it resultsProcessor;
        submit blobProcessor;
               before blobProcessor finishes, submit resultsProcessor;
}

也:

请看一下使用光纤提供无线并发的JetLang。