Поиск шаблонов регулярных выражений в наборе данных XML объемом 30 ГБ. Использование 16 ГБ памяти - PullRequest
3 голосов
/ 22 сентября 2008

В настоящее время у меня есть синтаксический анализатор Java SAX, который извлекает некоторую информацию из XML-файла объемом 30 ГБ.

В настоящее время это:

  • чтение каждого узла XML
  • сохраняя его в строковом объекте,
  • запускает некоторое регулярное выражение в строке
  • сохранение результатов в базе данных

Для нескольких миллионов элементов. Я запускаю это на компьютере с 16 ГБ памяти, но память используется не полностью.

Существует ли простой способ динамического «буферизации» данных из входного файла объемом около 10 ГБ?

Я подозреваю, что мог бы вручную взять многопотоковую версию «продюсер» «потребитель» (загрузка объектов с одной стороны, их использование и удаление с другой), но черт, XML сейчас древний, нет ли эффективных библиотек хрустеть им?

Ответы [ 10 ]

4 голосов
/ 22 сентября 2008
  1. Просто чтобы охватить основы, может ли Java использовать ваши 16 ГБ? Вы (очевидно) должны быть в 64-битной ОС, и вам нужно запустить Java с -d64 -XMx10g (или тем большим объемом памяти, который вы хотите выделить для него).

  2. Маловероятно, что память является ограничивающим фактором для того, что вы делаете, поэтому вы не должны видеть, что она полностью используется. Вы должны быть связаны с IO или CPU. Скорее всего, это будет IO. Если это так, IO, убедитесь, что вы буферизуете свои потоки, и тогда вы почти закончили; единственное, что вы можете сделать, это купить более быстрый жесткий диск.

  3. Если вы действительно привязаны к процессору, возможно, вы ограничены в регулярных выражениях, а не в разборе XML.

    См. это (что ссылается это )

  4. Если ваше узкое место в SAX, вы можете попробовать другие реализации. Сверху головы я могу подумать о следующих альтернативах:

    • StAX (существует несколько реализаций; Woodstox - один из самых быстрых)
    • Javolution
    • Сверните по своему усмотрению, используя JFlex
    • Сверните свое собственное объявление, например, используя регулярное выражение

    Для двух последних чем более ограниченным является ваше подмножество XML, тем эффективнее вы можете его сделать.

  5. Сложно сказать, но, как уже упоминалось, XML-база данных может быть хорошей альтернативой для вас. У меня ограниченный опыт работы с ними, но я знаю, что по крайней мере Berkeley DB XML поддерживает индексы на основе XPath.

2 голосов
/ 22 сентября 2008

SAX, по сути, «управляемый событиями», поэтому единственное состояние, которое вы должны удерживать от элемента к элементу, это состояние, относящееся к этому элементу, а не к документу в целом. Какое другое состояние вы поддерживаете и почему? По мере прохождения каждого «завершенного» узла (или набора узлов) их следует отбрасывать.

2 голосов
/ 22 сентября 2008

Сначала попытайтесь выяснить, что вас тормозит.

  • Насколько быстрее работает анализатор при разборе по памяти?
  • Помогает ли использование BufferedInputStream с большим размером?

Легко ли разделить файл XML? В целом, перетасовка 30 ГиБ данных любого типа займет некоторое время, так как вам сначала нужно загрузить их с жесткого диска, поэтому вы всегда ограничены скоростью этого. Можете ли вы распределить нагрузку на несколько машин, например, используя что-то вроде Hadoop ?

2 голосов
/ 22 сентября 2008

Нет опыта Java, извините, но, возможно, вам следует сменить парсер? SAX должен работать последовательно и не нужно буферизовать большую часть файла ...

1 голос
/ 22 сентября 2008

Вы можете использовать библиотеку Jibx и привязать свои XML-узлы к объектам, которые их представляют. Вы даже можете перегрузить ArrayList, затем, когда будет добавлено x число объектов, выполнить все регулярные выражения одновременно (предположительно, используя метод для вашего объекта, который выполняет эту логику), а затем сохранить их в базе данных, прежде чем разрешить метод "add" закончить еще раз.

Jibx размещен на SourceForge: Jibx

Для уточнения: вы можете связать свой XML как «коллекцию» этих специализированных держателей строк. Поскольку вы определяете это как коллекцию, вы должны выбрать, какой тип коллекции использовать. Затем вы можете указать свою собственную реализацию ArrayList.

Переопределите метод add следующим образом (забыл тип возвращаемого значения, например, предполагается void):

public void add(Object o) {
    super.add(o);
    if(size() > YOUR_DEFINED_THRESHOLD) {
        flushObjects();
    }
}

YOUR_DEFINED_THRESHOLD

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

1 голос
/ 22 сентября 2008

Тебя тормозит несколько небольших коммитов в твою БД? Звучит так, будто вы пишете в БД почти все время из вашей программы, и если вы делаете это не слишком часто, это может повысить производительность. Возможно, подготовка ваших заявлений и другие стандартные приемы массовой обработки могут помочь

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

1 голос
/ 22 сентября 2008

Я не совсем понимаю, что вы пытаетесь сделать с этим огромным количеством XML, но у меня складывается впечатление, что

  • использование XML неверно для хранимых данных
  • вы буферизуете намного больше того, что должны делать (и тем самым вы отказываетесь от всех преимуществ SAX-анализа)

Кроме того: XML не является древним и широко используется. Как вы думаете, что все эти интерактивные веб-сайты используют для своих интерактивных элементов?

0 голосов
/ 22 сентября 2008

Если данные в XML не зависят от порядка, можете ли вы выполнить многопоточность процесса, чтобы разделить файл или запустить несколько процессов, начинающихся в разных местах файла? Если вы не связаны с вводом / выводом, это должно помочь ускорить его.

0 голосов
/ 22 сентября 2008

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

0 голосов
/ 22 сентября 2008

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...