Bug #79700 [NEW]: wrong use of libxml oldNs leads to performance problem
| From: | beberlei@php.net | Date: | Mon, 15 Jun 2020 01:06:10 +0000 |
| Subject: | Bug #79700 [NEW]: wrong use of libxml oldNs leads to performance problem | ||
| Groups: | php.bugs | ||
| Request: | Send a blank email to php-bugs+get-227483@lists.php.net to get a copy of this message | ||
From: beberlei
Operating system:
PHP version: 7.4.7
Package: DOM XML related
Bug Type: Bug
Bug description:wrong use of libxml oldNs leads to performance problem
Description:
------------
In libxml, the xmlDoc->oldNs pointer is used by xmlSearchNs* functions
for holding the xmlns:xml namespace
"http://www.w3.org/XML/1998/namespace".
https://github.com/GNOME/libxml2/blob/mainline/include/libxml/tree.h#L140
https://github.com/GNOME/libxml2/blob/mainline/tree.c#L5992
The specification says this xml namespace MAY but need not be declared
on a document, but still exists implicitly.
This is what the xmlDoc->oldNs property is for, holding this namespace
outside the nodes. Usually a namespace is attached to a node.
PHP Dom however uses xmlDoc->oldNs to store any namespaces of new
namespaced elements or attributes during reconciliation. In combination
with a list append that does not check for duplicates this causes
exponential performance degradation in the number of nodes.
Test script:
---------------
<?php
$dom = new DOMDocument();
$root = $dom->createElementNS('http://www.w3.org/2000/xhtml',
'html');
$dom->appendChild($root);
$s = microtime(true);
for ($i = 0; $i < 10000; $i++) {
$element = $dom->createElementNS('http://www.w3.org/2000/xhtml',
'p', 'Hello World');
$root->appendChild($element);
}
echo number_format(microtime(true) - $s, 6) . "\n";
$s = microtime(true);
for ($i = 0; $i < 10000; $i++) {
$element = $dom->createElementNS('http://www.w3.org/2000/xhtml',
'p', 'Hello World');
$root->appendChild($element);
}
echo number_format(microtime(true) - $s, 6) . "\n";
$s = microtime(true);
for ($i = 0; $i < 10000; $i++) {
$element = $dom->createElementNS('http://www.w3.org/2000/xhtml',
'p', 'Hello World');
$root->appendChild($element);
}
echo number_format(microtime(true) - $s, 6) . "\n";
Expected result:
----------------
Roughly the same time for each block of 10000 nodes.
Actual result:
--------------
Time increases massively for each consecutive block from 200 ms to
1200ms to 2400ms (on my machine).
--
Edit bug report at https://bugs.php.net/bug.php?id=79700&edit=1
--
Fix committed: https://bugs.php.net/fix.php?id=79700&r=fixed
Fixed in release: https://bugs.php.net/fix.php?id=79700&r=alreadyfixed
Need backtrace: https://bugs.php.net/fix.php?id=79700&r=needtrace
Need Reproduce Script: https://bugs.php.net/fix.php?id=79700&r=needscript
Try newer version: https://bugs.php.net/fix.php?id=79700&r=oldversion
Not developer issue: https://bugs.php.net/fix.php?id=79700&r=support
Expected behavior: https://bugs.php.net/fix.php?id=79700&r=notwrong
Not enough info: https://bugs.php.net/fix.php?id=79700&r=notenoughinfo
Submitted twice: https://bugs.php.net/fix.php?id=79700&r=submittedtwice
register_globals: https://bugs.php.net/fix.php?id=79700&r=globals
PHP version support discontinued: https://bugs.php.net/fix.php?id=79700&r=phptooold
Daylight Savings: https://bugs.php.net/fix.php?id=79700&r=dst
IIS Stability: https://bugs.php.net/fix.php?id=79700&r=isapi
Install GNU Sed: https://bugs.php.net/fix.php?id=79700&r=gnused
Floating point limitations: https://bugs.php.net/fix.php?id=79700&r=float
No Zend Extensions: https://bugs.php.net/fix.php?id=79700&r=nozend
MySQL Configuration Error: https://bugs.php.net/fix.php?id=79700&r=mysqlcfg