Skip to content

Instantly share code, notes, and snippets.

@klopp
Last active October 8, 2020 18:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save klopp/262b0bbcb95151dea4beb356b705d132 to your computer and use it in GitHub Desktop.
Save klopp/262b0bbcb95151dea4beb356b705d132 to your computer and use it in GitHub Desktop.
Про парсеры XML
Поначалу захотелось Mojo::DOM. Когда-то использовал этот модуль в качестве замены HTML::DOM (он кошмарен),
и не разочаровался. Вменяемый набор методов, но... На XML от 100 Mb он так тормозил, что сразу отбросил.
OK, идём по классике: XML::LibXML. Из плюсов:
1) хороший комбайн с кучей возможностей (хотя, как и любое универсальное, для конкретных задач может быть громоздок)
2) вполне шустро
3) приятная мелочь: умеет обрабатывать NS в атрибутах (все следующие варианты - нет, и если мы не знаем заранее какие
NS могут встретиться, приходится заморачиваться отдельно; дальше отдельно про NS упоминать не буду)
Минусы:
1) см. предыдущий пункт 1, про комбайн :)
2) хочет много памяти
3) на файлах под полгига и больше может вылетать с совершенно невнятной диагностикой, например:
$ ls -sh psd7003.xml
684M psd7003.xml
$ ./xml-libxml.pl psd7003.xml
http error : Unknown IO error
Ссылка на код: https://gist.github.com/klopp/3fa3d0c6939fcafe1b29d827dfc9c315
Дальше пробую XML::Twig. Да, как и зявлено, на больших файлах, с которыми не справляется XML::LibXML, не помирает.
Но скорость... Пока перемолотит XML мегабайт в 500, можно выспаться. Плюс - тот же недостаток, памяти хочет.
Ссылка на код: https://gist.github.com/klopp/b479c2a1439314379b79008bbd084edd
Использовать для данной задачи XML::Twig с применением пользовательских обработчиков тегов смысла не вижу,
так как фактически это надстройка над XML::Parser. И, как показывают тесты, рабает гораздо медленний. Хотя
и имеет более гибкий набор методов.
Ну вот и он, XML::Parser. Весьма и весьма. Потребности в памяти минимальные и вообще не зависят от размера
файла. Работает шустро, ведь обработчики мы задаём сами и не делаем ничего лишнего. Но есть один минус: в обработчик
Char может прилетать ненужный для данной задачи мусор из пробелов и переводов строк. В качестве первого костыля стал
просто не учитывать строки, состоящие только из пробельных символов. Что для задачи не очень корректно.
Ссылка на код: https://gist.github.com/klopp/aadf718977ae698e407c2edf243310c3
Пробую другой костыль: ввести список тегов, внутри которых текст обрабатывается "as is", остальные пропускаем.
А почему бы и нет? В простейшем случае это параграф. Получается лучше, да и скорость.
Код: https://gist.github.com/klopp/28a1b3d32fbef549c8ac11c245375580
На данный момент это лидер. Но...
Как сишник не могу пройти мимо XML::Fast :) Да, память отжирает. Хоть и намного меньше LibXML/Twig. Но по скорости
уделывает всех:
$ ls -sh psd7003.xml
684M psd7003.xml
$ time ./xml-parser-tag.pl psd7003.xml
All characters : 2 970 951
Non-whitespace characters : 2 870 720
Internal links : 0
real 1m30.832s
user 1m30.524s
sys 0m0.172s
$ time ./xml-fast.pl psd7003.xml
All characters : 2 970 951
Non-whitespace characters : 2 870 720
Internal links : 0
real 0m55.859s
user 0m53.928s
sys 0m1.880s
$ ls -sh SwissProt.xml
110M SwissProt.xml
$ time ./xml-parser-tag.pl SwissProt.xml
All characters : 4 727 868
Non-whitespace characters : 4 697 952
Internal links : 0
real 0m16.518s
user 0m16.484s
sys 0m0.028s
$ time ./xml-fast.pl SwissProt.xml
All characters : 4 727 868
Non-whitespace characters : 4 697 952
Internal links : 0
real 0m11.848s
user 0m11.484s
sys 0m0.360s
Код: https://gist.github.com/klopp/0322d9d7fa8d3e1498951c5aa14a71d1
P.S. XML::Bare, XML::Hash::XS и XML::Simple рассматривать смысла не вижу.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment