在java中跟踪线程冲突



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

在24芯机器上,添加线程的好处在4以上时会很快减少。所以,我想,这里一定有一些争用或锁定,或者IO延迟,等等。

好吧,我打开了YourKit的"监控使用情况"功能,工作线程中显示的阻塞时间是微不足道的。通过观察线程状态图,工作线程几乎都是"绿色"(正在运行),而不是黄色(正在等待)或红色(已阻塞)。

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,每个blob大约有13个任务。因此,每个线程(假设有四个)每个blob大约调度3次。

硬件:我在我的MacBook pro上进行了小规模的测试,然后在linux上的一个大的Dell:hwinfo上报告了24个不同的项目——cpu,由组成

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

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

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

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

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

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

这很可能不是争用,尽管没有更多细节很难说。评测结果可能会产生误导,因为当线程在磁盘或网络I/O上被阻止时,Java会将其报告为RUNNABLE。Yourkit仍然将其计算为CPU时间。

最好的办法是打开CPU评测,深入了解工作线程中需要花费的时间。如果它最终主要出现在java.io类中,那么仍然存在磁盘或网络延迟。

您还没有完全并行化处理。在上一个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,它使用光纤提供了无线程并发。

最新更新