Java堆越慢越慢

时间:2014-02-10 07:56:41

标签: java performance heap heap-memory

我有一个在(大)图上运行的Java程序。因此,它使用了大量的堆空间(~50GB,约占主机上物理内存的25%)。有一次,程序(重复)从图中选择一个节点并用它进行一些计算。对于某些节点,此计算需要比预期更长的时间(30-60分钟,而不是预期的几秒钟)。为了分析这些操作以找出需要花费大量时间的内容,我创建了一个测试程序,它只创建大图的一小部分,然后在其中一个节点上运行相同的操作原计划。因此,与原始程序相比,测试程序显然只使用非常少的堆空间。

事实证明,在原始程序中花费48分钟的操作可以在测试程序中在9秒内完成。这真让我困惑。第一个想法可能是较大的程序花费大量时间进行垃圾收集。所以我打开了VM垃圾收集器的详细模式。据此,在48分钟内没有完整的垃圾收集,年轻一代只收集了20个收集,每个收集时间不到1秒。

所以我的问题是还有什么可以解释时间的巨大差异?我不太了解Java如何在内部组织堆。对于具有大量活动对象的大型堆,是否存在需要更长时间的事情?可能是在这样的设置中对象分配需要更长的时间,因为在堆中找到足够的位置需要更长的时间吗?或者VM是否会对堆进行任何内部重组,这可能需要花费大量时间(显然除了垃圾收集之外)。

我正在使用Oracle JDK 1.7,如果这有任何重要性。

2 个答案:

答案 0 :(得分:3)

虽然更大的记忆可能意味着更大的问题,但我会说没有什么(除了你已经排除的GC)什么可以延长9秒到48分钟(因子320)。

大堆使得空间局部看起来更糟糕,但我认为这不重要。我不同意蒂姆的答案w.r.t. “不得不为所有内容留下缓存”。

还有TLB虚拟地址转换的缓存,这可能会导致内存非常大的问题。但同样,不是因素320。

我认为JVM中没有任何可能导致此类问题的内容。

我能想象的唯一原因是你有一些交换空间可以使用 - 尽管你有足够的物理内存。即使轻微的交换也可能导致大幅放缓。确保它已关闭(并可能检查swappiness)。

答案 1 :(得分:0)

即使存在内存,您也可以在现代CPU上进行多级缓存数据。每次离开缓存以获取数据时,速度都会变慢。拥有50GB的ram很可能意味着它必须为所有内容留下缓存。

您描述的症状和差异虽然很大,但我没有看到像缓存一致性那样简单的事情,使 存在很大差异。

我可以给你的最好的建议是尝试运行一个分析器,当它运行缓慢和运行速度很快并比较差异时。

你需要扎实的数字和时间。 “在这个环境中做X花了Y时间”。从那以后你可以开始缩小范围。