java - 大型 Java 列表性能不佳

标签 java memory text garbage-collection large-files

我正在尝试使用 Java 将大型文本语料库读入内存。在某些时候它撞到了一堵墙,只是无休止地收集垃圾。我想知道是否有人有击败 Java 的 GC 以提交大型数据集的经验。

我正在阅读一个 8 GB 的英文文本文件,采用 UTF-8 格式,一行一行。我要split()每行放在空白处,并将生成的字符串数组存储在 ArrayList<String[]> 中用于进一步处理。这是一个显示问题的简化程序:

/** Load whitespace-delimited tokens from stdin into memory. */
public class LoadTokens {
    private static final int INITIAL_SENTENCES = 66000000;

    public static void main(String[] args) throws IOException {
        List<String[]> sentences = new ArrayList<String[]>(INITIAL_SENTENCES);
        BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
        long numTokens = 0;
        String line;

        while ((line = stdin.readLine()) != null) {
            String[] sentence = line.split("\\s+");
            if (sentence.length > 0) {
                sentences.add(sentence);
                numTokens += sentence.length;
            }
        }
        System.out.println("Read " + sentences.size() + " sentences, " + numTokens + " tokens.");
    }
}

看起来很简单,对吧?你会注意到我什至预先调整了我的 ArrayList ;我有不到 6600 万个句子和 13 亿个标记。现在如果你拿出你的Java object sizes引用和你的铅笔,你会发现应该需要:

  • 66e6 String[]引用 @ 8 字节 ea = 0.5 GB
  • 66e6 String[]对象 @ 32 字节 ea = 2 GB
  • 66e6 char[]对象 @ 32 字节 ea = 2 GB
  • 1.3e9 String引用 @ 8 字节 ea = 10 GB
  • 1.3e9 String s @ 44 字节 ea = 53 GB
  • 8e9 char s @ 2 字节 ea = 15 GB

83 GB。 (您会注意到我确实需要使用 64 位对象大小,因为 Compressed OOPs 无法帮助我处理 > 32 GB 的堆。)我们很幸运拥有一台具有 128 GB RAM 的 RedHat 6 机器,所以我从我的 Java SE 1.6.0_29 工具包中使用 pv giant-file.txt | java -Xmx96G -Xms96G LoadTokens 启动我的 Java HotSpot(TM) 64 位服务器 VM(构建 20.4-b02,混合模式)为了安全起见,在我观看 top 时退后一步.

在输入不到一半的地方,大约 50-60 GB RSS,并行垃圾收集器将 CPU 提高到 1300%(16 个 proc 框)并停止读取进度。然后它又增加了几 GB,然后进度停止了更长的时间。它已填满 96 GB,但尚未完成。我已经放了一个半小时,它只是消耗了大约 90% 的系统时间来做 GC。这似乎很极端。

为了确保我没有发疯,我编写了等效的 Python(所有两行;),它在大约 12 分钟内运行完成,RSS 为 70 GB。

那么:我是在做蠢事吗? (除了存储东西的通常效率低下,我真的帮不上忙——即使我的数据结构很胖,只要它们适合,Java 不应该只是窒息 .) 对于非常大的堆,是否有神奇的 GC 建议?我试过-XX:+UseParNewGC而且看起来更糟。

最佳答案

-XX:+UseConcMarkSweepGC :在 78 GB 和 ~12 分钟内完成。 (几乎和 Python 一样好!)感谢大家的帮助。

关于java - 大型 Java 列表性能不佳,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9593555/

相关文章:

Java 和 FTP 编辑在线文本文件

Java 8 计算具有多个值的对象

vb.net - 高级文本搜索并将特定字符串从文件导入 VB

Java Dispatching-Runtime类型

python - python中的内存错误

c++ - c++链表不再占用Ram空间?

sql-server - 如何强制 SQL Server 释放内存?

C# 应用程序 GUI 在不同的 Windows 图标/文本大小设置上中断

java - 计算 servlet 内的相对路径?

java - finally block 是否总是运行?