【问题标题】:Lucene Document creation in while loop slows down more and more在 while 循环中创建 Lucene 文档的速度越来越慢
【发布时间】:2014-10-26 17:04:19
【问题描述】:

我有一些效率问题。我正在开发一个部署在 jboss EAP 6.1 服务器上作为 EAR 存档的企业应用程序。我在 while 循环中基于实体创建新对象并将它们写入文件。我以有限的数量(例如每个步骤 2000 个)获得这些实体(在 EJB DAO 的帮助下)。问题是我需要处理数百万个对象,前一百万个进行得非常顺利,但进一步的循环运行得越慢。谁能告诉我为什么随着循环的进展,这个工作越来越慢?我怎样才能让它一直顺利运行?以下是代码的一些关键部分:

    public void createFullIndex(int stepSize) {
       int logsNumber = systemLogDao.getSystemLogsNumber();
       int counter = 0;
       while (counter < logsNumber) {
           for (SystemLogEntity systemLogEntity : systemLogDao.getLimitedSystemLogs(counter, stepSize)) {
               addDocument(systemLogEntity);
           }
           counter = counter + stepSize;
       }
       commitIndex();
    }

    public void addDocument(SystemLogEntity systemLogEntity) {
       try {
        Document document = new Document();
        document.add(new NumericField("id", Field.Store.YES, true).setIntValue(systemLogEntity.getId()));
        document.add(new Field("resource", (systemLogEntity.getResource() == null ? "" : systemLogEntity
                .getResource().getResourceCode()), Field.Store.YES, Field.Index.ANALYZED));
        document.add(new Field("operationType", (systemLogEntity.getOperationType() == null ? "" : systemLogEntity
        document.add(new Field("comment",
                (systemLogEntity.getComment() == null ? "" : systemLogEntity.getComment()), Field.Store.YES,
                Field.Index.ANALYZED));
        indexWriter.addDocument(document);
       } catch (CorruptIndexException e) {
           LOGGER.error("Failed to add the following log to Lucene index:\n" + systemLogEntity.toString(), e);
       } catch (IOException e) {
           LOGGER.error("Failed to add the following log to Lucene index:\n" + systemLogEntity.toString(), e);
       }
    }

感谢您的帮助!

【问题讨论】:

  • 您查看过堆统计信息吗?
  • @HotLicks 我想过但老实说我不太确定该怎么做。
  • indexWriter 是什么?似乎您正在向其中添加所有文档,并且它将保留对它们的引用,将它们保存在内存中。
  • @FlorentBayle 它是一个 Apache Lucene 类。我想我会尝试移动 commitIndex();正如其他人建议的那样,在 while 循环内。

标签: java performance while-loop lucene large-data


【解决方案1】:

据我所知,您并没有将您的东西写入文件。相反,您尝试创建完整的 DOM 对象,然后将其刷新到文件中。此策略适用于有限数量的对象。在您必须处理数百万个(如您所说)的情况下,您不应该使用 DOM。相反,您应该能够在接收数据时创建 XML 片段并将它们写入文件。这将减少您的内存消耗,并有望提高性能。

【讨论】:

  • 我认为这是一个影响最大的建议。谢谢!
【解决方案2】:

我会尝试重新使用 Document 对象。我在垃圾收集方面遇到了循环问题,我的循环太快以至于 gc 无法合理跟上,并且对象的重用解决了我的所有问题。我没有亲自尝试重用 Document 对象,但如果可能的话,它可能对你有用。

【讨论】:

  • 谢谢,这是一个合理的提示! +1
【解决方案3】:

记录应该很容易。使用 Guava 附加到文本看起来像:

File to = new File("C:/Logs/log.txt");
CharSequence from = "Your data as string\n";
Files.append(from, to, Charsets.UTF_8);

我的一些笔记:

  • 我不确定您的日志实体是否被垃圾回收
  • 不清楚文件内容是否保存在内存中
  • 如果日志是 xml 格式,那么在添加新元素时可能需要解析整个 XML DOM

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-05
    • 2020-01-23
    • 2023-03-12
    • 1970-01-01
    • 2020-03-26
    相关资源
    最近更新 更多