Bug #79211 [NEW]: DomXPath::query() has very inconsistent performance
| From: | tom at r dot je | Date: | Sun, 02 Feb 2020 04:35:24 +0000 |
| Subject: | Bug #79211 [NEW]: DomXPath::query() has very inconsistent performance | ||
| Groups: | php.bugs | ||
| Request: | Send a blank email to php-bugs+get-225301@lists.php.net to get a copy of this message | ||
From: tom at r dot je
Operating system: Linux
PHP version: 7.4.2
Package: DOM XML related
Bug Type: Bug
Bug description:DomXPath::query() has very inconsistent performance
Description:
------------
Here are three sample queries
Equivalent of the CSS
tr td.one
//tr//td[contains(concat(\' \', normalize-space(@class), \' \'), \' one
\')]
Equivalent of the CSS td.one
//td[contains(concat(\' \', normalize-space(@class), \' \'), \' one
\')]
Equivalent of the CSS tr td
//tr//td
There's a test script below that uses these queries on a 1000x6 HTML
table.
I'd expect them all to take roughly the same amount of time to run.
Test script:
---------------
<?php
$xml = '<table>';
for ($i = 0; $i < 1000; $i++) {
$xml .= '<tr><td class="one">A</td><td
class="two">B</td><td
class="three">C</td><td class="four">D</td><td
class="five">E</td><td
class="six">F</td>
</tr>';
}
$xml .= '</table>';
$doc = new \DomDocument;
$doc->loadXml($xml);
$xpath = new \DomXpath($doc);
$t1 = microtime(true);
// tr td.one
$xpath->query('//tr//td[contains(concat(\' \', normalize-space(@class),
\' \'), \' one \')]');
$t2 = microtime(true);
echo '<p>tr td.one: ' . ($t2 - $t1) . '</p>';
$t1 = microtime(true);
// td.one
$xpath->query('//td[contains(concat(\' \', normalize-space(@class), \'
\'), \' one \')]');
$t2 = microtime(true);
echo '<p>td.one: ' . ($t2 - $t1) . '</p>';
$t1 = microtime(true);
// tr td
$xpath->query('//tr//td');
$t2 = microtime(true);
echo '<p>tr td: ' . ($t2 - $t1) . '</p>';
Expected result:
----------------
While I'd expect some variation in speed, the first expression seems
unreasonably slow in comparison to the others.
Actual result:
--------------
tr td.one: 0.26365518569946
td.one: 0.0054380893707275
tr td: 0.00074887275695801
Finding all td elements by class name is fast
Finding all td elements inside a td is fast
Combining those, finding all td elements by class inside a tr is 50
times slower than just finding all td elements by class.
Since the first expression is a combination of the other two, how can it
be 50 times slower? It's clearly not the concat and normalize-space
functions that are slowing it down because the second expression is
fine.
--
Edit bug report at https://bugs.php.net/bug.php?id=79211&edit=1
--
Fix committed: https://bugs.php.net/fix.php?id=79211&r=fixed
Fixed in release: https://bugs.php.net/fix.php?id=79211&r=alreadyfixed
Need backtrace: https://bugs.php.net/fix.php?id=79211&r=needtrace
Need Reproduce Script: https://bugs.php.net/fix.php?id=79211&r=needscript
Try newer version: https://bugs.php.net/fix.php?id=79211&r=oldversion
Not developer issue: https://bugs.php.net/fix.php?id=79211&r=support
Expected behavior: https://bugs.php.net/fix.php?id=79211&r=notwrong
Not enough info: https://bugs.php.net/fix.php?id=79211&r=notenoughinfo
Submitted twice: https://bugs.php.net/fix.php?id=79211&r=submittedtwice
register_globals: https://bugs.php.net/fix.php?id=79211&r=globals
PHP version support discontinued: https://bugs.php.net/fix.php?id=79211&r=phptooold
Daylight Savings: https://bugs.php.net/fix.php?id=79211&r=dst
IIS Stability: https://bugs.php.net/fix.php?id=79211&r=isapi
Install GNU Sed: https://bugs.php.net/fix.php?id=79211&r=gnused
Floating point limitations: https://bugs.php.net/fix.php?id=79211&r=float
No Zend Extensions: https://bugs.php.net/fix.php?id=79211&r=nozend
MySQL Configuration Error: https://bugs.php.net/fix.php?id=79211&r=mysqlcfg