大堆的 Java 速度较慢

标签 java performance heap-memory

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

原来在原程序中需要 48 分钟的操作在测试程序中可以在 9 秒内完成。这真的让我很困惑。第一个想法可能是较大的程序在垃圾收集上花费了大量时间。所以我打开了虚拟机垃圾收集器的详细模式。据此,48 分钟内没有进行全量垃圾回收,新生代仅进行了约 20 次回收,每次回收不到 1 秒。

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

我正在使用 Oracle JDK 1.7,如果这很重要的话。

最佳答案

虽然更大的内存可能意味着更大的问题,但我认为没有什么(除了您排除的 GC)可以将 9 秒延长到 48 分钟(320 倍)。

大堆可能会导致看似更糟糕的空间局部性,但我认为这无关紧要。我不同意蒂姆的回答 w.r.t. “必须为所有内容保留缓存”。

还有 TLB这是一个用于虚拟地址转换的缓存,这可能会导致非常大的内存出现一些问题。但同样,不是因子 320。

我认为 JVM 中没有任何东西会导致此类问题。

我能想到的唯一原因是你有一些被使用的交换空间——尽管你有足够的物理内存。即使是轻微的交换也可能导致巨大的减速。确保它已关闭(并可能检查 swappiness )。

关于大堆的 Java 速度较慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21671725/

相关文章:

ruby - Ruby 2.2.0 中的混编比 2.1.5 慢

ios - 我想在分析后使用 .traces 文件创建一个仪表板(Xcode Instrument)。是否可以?

java - 在java 2d中采摘

java - Android SQLite数据库未完全提交?更改直到 Activity 结束?

java - BodyEditorLoader - 读取文件时出错

java - Java中并发管道的策略

java - Python 脚本未在 Java 中输出

performance - 为什么reshape这么快? (剧透 : Copy-on-Write)

c++ - 当存在 std::vector 时,强指针导致应用程序关闭时堆损坏

java - 无法将 Java 堆大小设置为大于 1568