26 декабря 2009

Fast iterating over xml nodes by MSXML

Волею судеб мне приходится иметь дело с MSXML. Не самая лучшая библиотека для работы с xml, но так вот получилось. И будучи любителем конструкции for_each, обход дочерних нод в моем коде выглядит так:
BOOST_FOREACH(IXMLDOMNodePtr Node, ChildNodes(RootNode))
DoSomething(Node);
ChildNodes отдает пару итераторов, которые дают доступ по IXMLDOMNodeList через IXMLDOMNodeList::item(). Так вот на обработке большого xml файла заметил, что такая конструкция очень жутко тормозит. Я было хотел списать все это со словами "ну этож MSXML тормозная - ничего не поделаешь...". Но как оказалось, правдива только первая часть этой фразы, а "поделать" все-таки что-то можно: если перебирать ноды через IXMLDOMNodeList::nextNode(), то вместо исходных 450мс получалось обойти ноды всего за 28:
IXMLDOMNodeListPtr NodeList = RootNode->childNodes;
for (IXMLDOMNodePtr Node; Node = NodeList->nextNode(); )
DoSomething(Node);

Видимо про такие случаи Спольски рассказывал байку про маляра, который красил забор. За первый день он покрасил 20 метров забора, за второй - 10, за третий - всего 2 (цифры привожу по памяти, память дырявая). Когда его спросили, почему он так стал тормозить, ответ был великолепен: "Насяльника, так за краской все дальше и дальше ходить!" Видимо IXMLDOMNodeList::item() работает таким же образом, как и тот маляр, так что beware!

3 комментария:

Alex Ott комментирует...

а на arabica не смотрели? оно такие вещи прячет за однообразным интерфейсам к разным парсерам...

Raider комментирует...

нет, не знал про такую - посмотрю, спасибо за инфу.
ps. и это... вполне можно на "ты"

Dobrovestnik комментирует...

А на dobrovestnik.ru не смотрели? там все сделано по технологии treemap.