Создание документа Lucene во время цикла все больше замедляется

У меня проблемы с эффективностью. Я разрабатываю корпоративное приложение, которое развертывается на сервере JBoss EAP 6.1 как архив EAR. Я создаю новые объекты на основе сущностей в цикле while и записываю их в файл. Я получаю эти объекты (с помощью EJB DAO) в ограниченном количестве (например, 2000 для каждого шага). Проблема в том, что мне нужно обрабатывать миллионы объектов, и первый миллион идет довольно гладко, но дальнейшая петля идет медленнее, чем работает. Может ли кто-нибудь сказать мне, почему это работает медленнее и медленнее по мере продвижения циклы? Как я могу заставить его работать плавно всю дорогу? Вот некоторые важные части кода:

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);
 }
 }

Буду признателен за вашу помощь!

3 ответа

Насколько я вижу, вы не пишете свои материалы, насколько можете. Вместо этого вы пытаетесь создать полный объект DOM, а затем очистите его до файла. Эта стратегия хороша для ограниченного количества объектов. В вашем случае, когда вам приходится иметь дело с миллионами из них (как вы сказали), вы не должны использовать DOM. Вместо этого вы должны иметь возможность создавать свои XML-фрагменты и записывать их в файл во время получения данных. Это уменьшит потребление памяти и, надеюсь, улучшит производительность.


Я бы попробовал повторно использовать объект Document. У меня были проблемы с циклом с сборкой мусора, где мои циклы слишком быстрые, чтобы gc мог нормально идти в ногу, и повторное использование объектов решило все мои проблемы. Я не пробовал повторно использовать объект Document лично, но если это возможно, это может сработать для вас.


Ведение журнала должно быть легким. Использование добавления 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 может быть проанализирован, если новый элемент добавлен

licensed under cc by-sa 3.0 with attribution.