[Fwd: [Bratislava-pm] XML::LibXML performance]

Michael Kröll <[email protected]>
Newsgroups gmane.comp.lang.perl.xml
Message-ID <[email protected]>
Interesting findings on XML::LibXML performance - English text starting
after the Slovak version.

Attachments at
http://mail.pm.org/pipermail/bratislava-pm/2008-September/000107.html

--michael

-------- Original Message --------
Subject: [Bratislava-pm] XML::LibXML performance
Date: Tue, 09 Sep 2008 23:41:07 +0200
From: Emmanuel Rodriguez <[email protected]>
To: [email protected]

Ahojte,

Jozef mi povedal cez víkend, že mal Perl kód ktorý používal XML::LibXML
a bol veľmi pomalý. Ak si dobre pamätám, prvá verzia potrebovala asi 20
sekúnd a potom Jozef urobil druhú verziu, ktorá potrebovala 1.5 sekundy.
Prvá verzia používala veľa XPath tak nebola taká rýchla, druhá verzia
používala XPath len jeden krát a bola rýchlejšia a potom urobila všetko
cez normálny DOM. Keď je XML jednoduché, lepšie je použiť DOM ako XPath
aj keď kód bude trochu dlhší ale program bude rýchlejší.

Bol som veľmi zvedavý lebo používam veľa XML::LibXML a chcel by som
vidieť v čom bol problém. Pracoval som trochu s Jozefovým kódom a teraz
máme verziu, ktorá potrebuje len pol sekundy, ale to je tiež pomalé
podľa mňa.

Súbor je asi 474K a má 17743 elementy, čo nie je veľa ale čítať tento
súbor nie je v Perle veľmi rýchle. Meral som rýchlosti a zistil som, že
chodiť cez celý strom v C je veľmi rýchle a potrebuje len 0.030 sekundy,
ale v Perle to isté potrebuje 0.450 sekundy, a to je 15 krát pomalšie!

V C chodiť cez DOM je veľmi ľahké a rýchle lebo všetko je cez "pointers"
napríklad:
node = node->next;
if (node->type == XML_ELEMENT_NODE)
process_element(node->children);

Ale v Perle to isté nemôže byt cez "pointers" a tento kód musí používať
funkcie:
$node = $node->nextSibling();
if ($node->nodeType == XML_ELEMENT_NODE)
process_element($node->firstChild());

Neviem presne prečo kód je taký pomalý v Perle, myslím že to je lebo
máme veľa elementy a každý DOM operácia potrebuje jeden funkcia v Perl.
Možno XS je drahý? Pozeral som XS kód a tieto tri funkcie sú veľmi krátke:

SV*
nextSibling( self )
xmlNodePtr self
ALIAS:
getNextSibling = 1
CODE:
RETVAL = PmmNodeToSv( self->next,
PmmOWNERPO(PmmPROXYNODE(self)) );
OUTPUT:
RETVAL

int
nodeType( self )
xmlNodePtr self
ALIAS:
XML::LibXML::Node::getType = 1
CODE:
RETVAL = self->type;
OUTPUT:
RETVAL

SV*
firstChild( self )
xmlNodePtr self
ALIAS:
getFirstChild = 1
CODE:
RETVAL = PmmNodeToSv( self->children,
PmmOWNERPO( PmmPROXYNODE(self) ) );
OUTPUT:
RETVAL

----
Hi,

This weekend Jozef told that he had a Perl program that was using
XML::LibXML which as very slow. If I recall well, the first version of
his program needed in average 20 seconds. Latter Jozef made a second
version which needed only 1.5 seconds. His first version was using
exhaustively XPath while the second version used XPath only once and
replaced the other calls by simple DOM references. Xpath is very nice
when dealing with complex documents or when the queries are very narrow,
but when the XML is simple, the best is to revert to DOM, sure the code
will be slightly longer but the gain in speed will be considerable.

Never the less, I was puzzled by the problem that plagued Jozef's code,
specially because I'm using a lot XML::LibXML and I wanted to know that
was the source of the problem. I managed to work a little bit with
Jozef's sample code and I managed to remove a second from the execution
time. But passing from 1.5 seconds to 0.5 it's not too convincing, the
program is still slow.

It's interesting to notice that the input file used has 474K and
contains 17743 elements. That's not a lot, but still parsing such an
input file in Perle is very slow. I benchmarked the program and I found
out that walking through the DOM tree in C is very fast and can be done
in 0.030 seconds, but in Perl the same operation needs 0.450 seconds,
that's 15 times slower!

I think that the reason of the speed difference is due to the way that
the DOM tree is walked. In C crossing the DOM tree is not expensive and
is very fast as everything is done through pointers, for instance:
node = node->next;
if (node->type == XML_ELEMENT_NODE)
process_element(node->children);

But in Perl this same operation can't be done through pointers a the
same program needs to use functions instead:
$node = $node->nextSibling();
if ($node->nodeType == XML_ELEMENT_NODE)
process_element($node->firstChild());

I'm not sure why the same code in Perl is so slow. I think that the
problem is not due to the size of the input file but to the numbers of
elements in the XML document. Probably that the number is so high that
the XS method calls are becoming quite expensive. I took a look a the XS
code and the functions are as short as they can be:

SV*
nextSibling( self )
xmlNodePtr self
ALIAS:
getNextSibling = 1
CODE:
RETVAL = PmmNodeToSv( self->next,
PmmOWNERPO(PmmPROXYNODE(self)) );
OUTPUT:
RETVAL

int
nodeType( self )
xmlNodePtr self
ALIAS:
XML::LibXML::Node::getType = 1
CODE:
RETVAL = self->type;
OUTPUT:
RETVAL

SV*
firstChild( self )
xmlNodePtr self
ALIAS:
getFirstChild = 1
CODE:
RETVAL = PmmNodeToSv( self->children,
PmmOWNERPO( PmmPROXYNODE(self) ) );
OUTPUT:
RETVAL

For the curious I have joined the programs that I've used to parse the
files. These programs simply perform a walk of the whole DOM tree. These
benchmarks are interesting because they show that scanning the whole XML
file in Perl can't be done in less than 0.450 seconds that's why the
fastest version of Jozef's parser is doomed to work in about half a
second. No matter the algorithm that I've used, I couldn't go under the
0.500 second barrier. This is as fast as it gets with the current
implementation of XML::LibXML.



-- 
063A F25E B064 A98F A479  1690 78CD D023 5E2A 6688
http://zis.uibk.ac.at/.m/uibk.ac.at_pgp_pubkey.asc

_______________________________________________
Perl-XML mailing list
[email protected]
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.