4

我有一个无法解决的性能问题。我正在编写一个解析巨大(> 2000 万行)文本文件并将某些信息存储在 Set 中的 Java 应用程序。我以每百万行的秒数来衡量性能。由于我需要大量内存,我通常使用 -Xmx6000m 和 -Xms4000m 运行程序。

如果我只是运行程序,它会在大约 6 秒内解析 100 万行。但是,经过一些性能调查后,我意识到,如果我在实际解析例程之前添加此代码,性能会增加到每 100 万行不到 3 秒:

BufferedReader br = new BufferedReader(new FileReader("graphs.nt"));
HashMap<String, String> foo = new HashMap<String, String>();
String line;
while ((line = br.readLine()) != null){
    foo.put(line, "foo");
}
foo = null;
br.close();
br = null;

graphs.nt 文件大约有 900 万行。即使我不将 foo 设置为 null,性能仍然会提高,这主要是为了证明该地图实际上没有被程序使用。

其余代码完全不相关。我使用来自 openrdf sesame 的解析器来读取不同的(不是 graphs.nt)文件,并将提取的信息存储在由另一个对象创建的新 HashSet 中。在其余代码中,我创建了一个Parser 对象,我将一个Handler 对象传递给该对象

这真的让我很困惑。我的猜测是,这以某种方式驱动 JVM 为我的程序分配更多内存,当我运行 top 时,我可以看到提示。如果没有 HashMap,它将分配大约 1 Gig 的内存。如果我初始化 HashMap,它将分配 > 2 Gigs。

我的问题是,这听起来是否合理。创建这么大的对象是否有可能为程序分配更多的内存以供以后使用?-Xmx 和 -Xms 不应该控制内存分配,还是有其他可能在这里起作用的参数?

我知道这似乎是一个奇怪的问题,而且信息很少,但这是我发现的与该问题相关的所有信息。如果有更多可能有用的信息,我非常乐意提供。

4

3 回答 3

0

这听起来像文件缓存?您的文件“graphs.nt”可能由操作系统或 JVM 缓存在 RAM 中。由于性能原因,GC 将允许内存消耗增加,如果您在预加载后立即添加强制收集System.gc(),您将能够判断缓存是发生在 JVM 中还是在 OS 中。

于 2013-10-14T12:24:49.600 回答
0

除非您不遗余力地做到这一点,否则“foo”最终将超出范围并被收集,即使您没有将指针为零,即使包含上述代码的方法从未退出也是如此。但这将迫使堆变大,这将减少 GC 的相对开销。

(在程序末尾引用“foo”将是一个有趣的实验,以使其保持在范围内。)

于 2013-07-22T19:11:30.350 回答
0

内存和 GC 肯定会影响性能。如果可能,您应该运行 Xms==Xmx 来禁用调整大小,并在启动时给 JVM 足够的空间。您的应用程序可能会在需要任何主要 GC 之前退出。

于 2013-07-22T18:30:22.483 回答