1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 00:02:20 +01:00

dom: Optimize splitText() (#20371)

This avoids duplicating the intermediate strings, by transferring
ownership.

It's hard to measure the improvement in a reliable way, as we have to
operate on the same node. The following benchmark shows a nice
improvement (although not perfect as a benchmark):
```php
<?php

$dom = new DOMDocument;
$dom->loadXML('<root>testabcdef</root>');
$text = $dom->documentElement->firstChild;

for ($i = 0; $i < 1000000; $i++) {
    $text2 = clone $text;
    $text2->splitText(5);
}
```

Only tested on my desktop i7-4790:
```
Benchmark 1: ./sapi/cli/php x.php
  Time (mean ± σ):     284.1 ms ±   2.8 ms    [User: 280.0 ms, System: 3.0 ms]
  Range (min … max):   281.4 ms … 291.3 ms    10 runs

Benchmark 2: ./sapi/cli/php_old x.php
  Time (mean ± σ):     314.0 ms ±   7.8 ms    [User: 309.2 ms, System: 2.9 ms]
  Range (min … max):   306.5 ms … 328.0 ms    10 runs

Summary
  ./sapi/cli/php x.php ran
    1.11 ± 0.03 times faster than ./sapi/cli/php_old x.php
```
This commit is contained in:
Niels Dossche
2025-11-03 18:46:56 +01:00
committed by GitHub
parent bda37c1161
commit 540fd6e96b
2 changed files with 9 additions and 5 deletions

View File

@@ -117,5 +117,8 @@ PHP 8.6 UPGRADE NOTES
. Arguments are now passed more efficiently to known constructors (e.g. when
using new self()).
- DOM:
. Made splitText() faster and consume less memory.
- JSON:
. Improve performance of encoding arrays and objects.

View File

@@ -127,17 +127,18 @@ PHP_METHOD(DOMText, splitText)
first = xmlUTF8Strndup(cur, (int)offset);
second = xmlUTF8Strsub(cur, (int)offset, (int)(length - offset));
xmlNodeSetContent(node, first);
nnode = xmlNewDocText(node->doc, second);
xmlFree(first);
xmlFree(second);
xmlNodeSetContent(node, NULL);
node->content = first;
nnode = xmlNewDocText(node->doc, NULL);
if (nnode == NULL) {
xmlFree(second);
php_dom_throw_error(INVALID_STATE_ERR, /* strict */ true);
RETURN_THROWS();
}
nnode->content = second;
if (node->parent != NULL) {
nnode->type = XML_ELEMENT_NODE;
xmlAddNextSibling(node, nnode);