Skip to content

Commit 540fd6e

Browse files
authored
dom: Optimize splitText() (php#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 ```
1 parent bda37c1 commit 540fd6e

File tree

2 files changed

+9
-5
lines changed

2 files changed

+9
-5
lines changed

UPGRADING

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,5 +117,8 @@ PHP 8.6 UPGRADE NOTES
117117
. Arguments are now passed more efficiently to known constructors (e.g. when
118118
using new self()).
119119

120+
- DOM:
121+
. Made splitText() faster and consume less memory.
122+
120123
- JSON:
121124
. Improve performance of encoding arrays and objects.

ext/dom/text.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -127,17 +127,18 @@ PHP_METHOD(DOMText, splitText)
127127
first = xmlUTF8Strndup(cur, (int)offset);
128128
second = xmlUTF8Strsub(cur, (int)offset, (int)(length - offset));
129129

130-
xmlNodeSetContent(node, first);
131-
nnode = xmlNewDocText(node->doc, second);
132-
133-
xmlFree(first);
134-
xmlFree(second);
130+
xmlNodeSetContent(node, NULL);
131+
node->content = first;
132+
nnode = xmlNewDocText(node->doc, NULL);
135133

136134
if (nnode == NULL) {
135+
xmlFree(second);
137136
php_dom_throw_error(INVALID_STATE_ERR, /* strict */ true);
138137
RETURN_THROWS();
139138
}
140139

140+
nnode->content = second;
141+
141142
if (node->parent != NULL) {
142143
nnode->type = XML_ELEMENT_NODE;
143144
xmlAddNextSibling(node, nnode);

0 commit comments

Comments
 (0)