问题
我有一段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,但是我的技能很弱:它是一个复杂的工具,我还不了解。我收到了订购书:给自己一个有趣的圣诞节礼物,但是为时不晚,无法解决我当前的问题
题
后来的许多实验中,我发现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哈希图的创建都会导致应用程序停止可伸缩性(我夸大了但不多)。我的应用程序确实大量使用了哈希图,所以我想我要么重写哈希图,要么重写应用程序。
我在提出一个单独的问题,以查看如何处理。
谢谢你的帮助