2010-11-17 3 views
9

Я пишу приложение, которое обрабатывает много XML-файлов (> 1000) с глубокими структурами узлов. Требуется около шести секунд с помощью woodstox (Event API) для анализа файла с 22 000 узлов.Параллельный анализ XML в Java

Алгоритм помещается в процесс с пользовательским взаимодействием, где допустимо только несколько секунд отклика. Поэтому мне нужно улучшить стратегию обработки XML-файлов.

  1. Мой процесс анализирует XML-файлы (извлекает только несколько узлов).
  2. Обработанные фрагменты обрабатываются, и новый результат записывается в новый поток данных (в результате получается копия документа с модифицированными узлами).

Теперь я думаю о многопоточном решении (которое масштабируется лучше на 16-ядерном оборудовании). Я думал о следующих стратегиях:

  1. Создание нескольких парсеров и их параллельное использование в источниках xml.
  2. Переписывая мой алгоритм синтаксического анализа потоков сохранить использовать только один экземпляр парсера (фабрики, ...)
  3. Split источник XML на куски и назначить куски в несколько потоков обработки (map-reduce xml - serial)
  4. Оптимизация моего алгоритм (лучше StAX анализатор чем Woodstox?)/Использование парсера с встроенным параллелизмом

Я хочу, чтобы улучшить и, производительность в целом и «в файл» производительность.

У вас есть опыт работы с такими проблемами? Каков наилучший способ?

+0

Непонятно, что здесь нужно максимизировать ... производительность в файле SINGLE или общую производительность на всех 1000 файлах. –

+0

Еще одно предложение: если вы можете количественно определить размеры файлов, чтобы позволить вычислять всю (обработанные мегабайты в секунду), это может дать представление о ожидаемой производительности. Я обычно получаю 10 - 40 МБ/с для разбора с помощью Woodstox при тестировании; но мои жесткие диски могут обеспечить только 5 - 10 Мбайт/с. – StaxMan

+0

Вы посмотрели на vtd-xml? это современное состояние в области тяжелой обработки ... оно намного эффективнее SAX или stax? –

ответ

4
  1. Это очевидно: просто создайте несколько парсеров и выполните их параллельно в нескольких потоках.

  2. Посмотрите на Woodstox Performance (на данный момент попробуйте кеш Google).

  3. Это может быть сделано. Структура IF вашего XML предсказуема: если у нее много одинаковых элементов верхнего уровня. Например:

    <element> 
        <more>more elements</more> 
    </element> 
    <element> 
        <other>other elements</other> 
    </element> 
    

    В этом случае вы можете создать простой разветвитель, который ищет <element> и питает эту часть к конкретному экземпляру синтаксического анализатора.Это упрощенный подход: в реальной жизни я бы пошел с RandomAccessFile, чтобы найти точки старта (<element>), а затем создать пользовательский FileInputStream, который работает только с частью файла.

  4. Посмотрите на Aalto. Те же ребята, которые создали Woodstox. Это эксперты в этой области - не изобретайте велосипед.

4

Я согласен с Джим. Я думаю, что если вы хотите улучшить производительность общей обработки 1000 файлов, ваш план хорош, кроме # 3, что в данном случае не имеет значения. Если вы хотите улучшить производительность анализа одного файла, у вас есть проблема. Я не знаю, как можно разделить XML-файл без его разбора. Каждый фрагмент будет незаконным XML, и ваш синтаксический анализатор завершится с ошибкой.

Я считаю, что улучшение общего времени достаточно для вас. В этом случае прочитайте этот учебник: http://download.oracle.com/javase/tutorial/essential/concurrency/index.html затем создайте пул потоков, например, 100 потоков и очереди, которые содержат источники XML. Каждый поток будет анализировать только 10 файлов, которые принесут серьезную выгоду производительности в многопроцессорной среде.

+0

+1: Хотя это может не улучшить производительность, если синтаксический анализ достаточно прост, что основной проблемой является IO. –

2

В дополнение к существующим хорошим предложениям есть одна довольно простая вещь: использовать API-интерфейс курсора (XMLStreamReader), НЕ Event API. Event API добавляет 30-50% накладных расходов (только IMO), что значительно облегчает процесс обработки. На самом деле, если вы хотите удобства, я бы рекомендовал вместо этого использовать StaxMate; он основывается на API-интерфейсе курсора, не добавляя значительных накладных расходов (не более 5-10% по сравнению с рукописным кодом).

Теперь: предположим, вы сделали базовые оптимизации с помощью Woodstox; но если нет, проверьте «3 Simple Rules for Fast XML-processing using Stax». В частности, вы абсолютно необходимо:

  1. Убедитесь, что вы только создать XMLInputFactory и XMLOutputFactory экземпляры раз
  2. Закрыть читатели и писатели, чтобы обеспечить рециркуляцию буфера (и другую полезную повторное) работает, как ожидалось.

Причина, по которой я упоминаю об этом, заключается в том, что, хотя они не имеют функциональной разницы (код работает так, как ожидалось), они могут иметь большую разницу в производительности; хотя более того, при обработке небольших файлов.

Выполнение нескольких экземпляров также имеет смысл; хотя обычно имеет не более 1 потока на ядро. Однако вы получите выгоду только в том случае, если ваш накопитель ввода/вывода может поддерживать такие скорости; если диск является узким местом, это не поможет и может в некоторых случаях повредить (если диск ищет конкурентов). Но стоит попробовать.

Смежные вопросы