一尘不染

除了互斥锁或垃圾回收以外,还有哪些机制可以减慢我的多线程Java程序?

java

问题

我有一段Java代码(如果相关,则为JDK 1.6.0._22),可实现无互斥的无状态,无副作用的功能。但是,它确实占用大量内存(我不知道这是否相关)。

过去,我曾访问过Sun
Laboratories,并收集了标准的“性能与线程数”曲线。由于此函数没有互斥体,因此它具有一个不错的图形,尽管随着线程数量的增加,垃圾回收也开始了。经过一些垃圾收集调整之后,我能够使该曲线几乎平坦。

我现在在Intel硬件上进行相同的实验。硬件有4个CPU,每个CPU都有8个内核和超线程。这给出了64个availableProcessors()。不幸的是,“性能与线程数”的曲线很好地缩放了1、2、3个线程,上限为3个线程。3个线程之后,我可以根据需要为任务分配尽可能多的线程,而性能却没有任何改善

尝试解决问题

我最初的想法是我很愚蠢,并在某个地方引入了一些同步代码。通常,要解决此问题,我运行JConsole或JVisualVM,并查看线程堆栈跟踪。如果我有64个线程以3的速度运行,那么我希望其中有61个线程正等待输入互斥体。我没找到这个。相反,我发现所有线程都在运行:非常缓慢。

第二个想法是,时间框架可能会引入问题。我用一个虚拟函数替换了我的函数,使用AtomicLong可以算出十亿。这可以通过线程数进行漂亮的扩展:使用64个线程比使用1个线程,我可以算出10倍10,000倍的10,000倍。

我以为(绝望的开始)垃圾回收确实花费了很长时间,所以我调整了垃圾回收参数。尽管这改善了我的延迟变化,但对吞吐量没有影响:我仍然有64个线程以我希望3的速度运行。

我已经下载了英特尔工具VTunes,但是我的技能很弱:它是一个复杂的工具,我还不了解。我收到了订购书:给自己一个有趣的圣诞节礼物,但是为时不晚,无法解决我当前的问题

  1. 我可以使用哪些工具(心理或软件)来加深对正在发生的事情的了解?
  2. 除了互斥锁或垃圾回收以外,还有哪些机制可能会降低我的代码速度?

阅读 203

收藏
2020-12-03

共1个答案

一尘不染

后来的许多实验中,我发现JVM没什么作用,但我也发现了JDump的强大功能。64个线程中的50个位于以下行。

java.lang.Thread.State: RUNNABLE
    at java.util.Random.next(Random.java:189)
    at java.util.Random.nextInt(Random.java:239)
    at sun.misc.Hashing.randomHashSeed(Hashing.java:254)
    at java.util.HashMap.<init>(HashMap.java:255)
    at java.util.HashMap.<init>(HashMap.java:297)

Random.next看起来像这样

 protected int next(int bits) {
    long oldseed, nextseed;
    AtomicLong seed = this.seed;
    do {
        oldseed = seed.get();
        nextseed = (oldseed * multiplier + addend) & mask;
    } while (!seed.compareAndSet(oldseed, nextseed));
    return (int)(nextseed >>> (48 - bits));
 }

最有趣的是,这并不是一个明显的锁,因此我用来发现互斥锁的工具无法正常工作。

因此,似乎任何Java哈希图的创建都会导致应用程序停止可伸缩性(我夸大了但不多)。我的应用程序确实大量使用了哈希图,所以我想我要么重写哈希图,要么重写应用程序。

我在提出一个单独的问题,以查看如何处理。

谢谢你的帮助

2020-12-03