【问题标题】:GC overhead limit exceeded when reading large pipe-separated values file读取大型管道分隔值文件时超出 GC 开销限制
【发布时间】:2017-06-08 10:05:09
【问题描述】:

我正在尝试解析一个大文件(650 万行),但遇到了上述内存不足错误。我正在使用相同的方法来读取大约 50K 行的其他文件,并且它工作得相当快。在这里它运行得非常慢,然后因错误而失败。我最初有 2 GB 专用于 intelliJ,我将其更改为 4 GB (-Xmx4000m),然后是 6 GB (-Xmx6000m),但仍然以同样的错误结束。我的电脑只有 8 GB RAM,所以我不能再高了。有什么建议吗?

谢谢!

public static List<UmlsEntry> umlsEntries(Resource resource) throws 
 IOException {
 return CharStreams.readLines(new InputStreamReader(resource.getInputStream())).stream().distinct()
    .map(UmlsParser::toUmlsEntry).collect(Collectors.toList());
}

private static UmlsEntry toUmlsEntry(String line) {
 String[] umlsEntry = line.split("|");

 return new UmlsEntry(umlsEntry[UNIQUE_IDENTIFIER_FOR_CONCEPT_COLUMN_INDEX],
    umlsEntry[LANGUAGE_OF_TERM_COLUMN_INDEX], umlsEntry[TERM_STATUS_COLUMN_INDEX],
    umlsEntry[UNIQUE_IDENTIFIER_FOR_TERM_COLUMN_INDEX], umlsEntry[STRING_TYPE_COLUMN_INDEX],
    umlsEntry[UNIQUE_IDENTIFIER_FOR_STRING_COLUMN_INDEX],
    umlsEntry[IS_PREFERRED_STRING_WITHIN_THIS_CONCEPT_COLUMN_INDEX],
    umlsEntry[UNIQUE_IDENTIFIER_FOR_ATOM_COLUMN_INDEX], umlsEntry[SOURCE_ASSERTED_ATOM_INDENTIFIER_COLUMN_INDEX],
    umlsEntry[SOURCE_ASSERTED_CONCEPT_IDENTIFIER_COLUMN_INDEX],
    umlsEntry[SOURCE_ASSERTED_DESCRIPTOR_IDENTIFIER_COLUMN_INDEX],
    umlsEntry[ABBREVIATED_SOURCE_NAME_COLUMN_IDENTIFIER_COLUMN_INDEX],
    umlsEntry[ABBREVIATION_FOR_TERM_TYPE_IN_SOURCE_VOCABULARY_COLUMN_INDEX],
    umlsEntry[MOST_USEFUL_SOURCE_ASSERTED_IDENTIFIER_COLUMN_INDEX], umlsEntry[STRING_COLUMN_INDEX],
    umlsEntry[SOURCE_RESTRICTION_LEVEL_COLUMN_INDEX], umlsEntry[SUPPRESSIBLE_FLAG_COLUMN_INDEX],
    umlsEntry[CONTENT_VIEW_FLAG_COLUMN_INDEX]);
 }

【问题讨论】:

  • 请发布堆栈跟踪。哪一行导致了错误?
  • 啊我没有复制它,我出去吃午饭时会运行它,它占用了我所有的内存,所以我几乎不能做任何其他事情。很快就会联系...

标签: java parsing delimiter large-files


【解决方案1】:

您需要一次处理几行以避免耗尽所有可用内存,因为文件不适合内存。 CharStreams.readLines 令人困惑的是不是流媒体。它一次读取所有行并返回一个列表。这行不通。请改用File.lines。我怀疑你也会遇到distinct 的麻烦。它需要跟踪所有行的所有哈希,如果这个气球太远,你可能也必须改变那个策略。哦,如果您没有足够的内存来保存结果,collect 也将不起作用。然后你可能想要写入一个新文件或数据库等等。

这是一个示例,说明如何从文件中流式传输行、计算不同的条目并打印每行的 md5:

Files.lines(FileSystems.getDefault().getPath("/my/file"))
            .distinct()
            .map(DigestUtils::md5)
            .forEach(System.out::println);

如果您在检测不同行时遇到问题,请先对文件进行就地排序,然后仅过滤掉相同的相邻行。

【讨论】:

  • 是的,事实证明我的机器功能不够强大,无法像我的所有程序一样在不退出的情况下保存整个列表。可以很好地加载所有行,但是添加到列表中,一旦超过 100 万行,就会变得非常慢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-21
  • 2018-10-25
  • 1970-01-01
  • 2017-02-24
  • 2017-12-27
相关资源
最近更新 更多