[php-src] Issue #9003: Bad performances on substr_replace on large strings

From: Date: Wed, 13 Jul 2022 16:14:43 +0000
Subject: [php-src] Issue #9003: Bad performances on substr_replace on large strings
Groups: php.bugs 
Request: Send a blank email to php-bugs+get-241920@lists.php.net to get a copy of this message
Issue: https://github.com/php/php-src/issues/9003 Author: cedric-anne ### Description During analysis of a performance issue on a project I work on, I figured out that doing many replacement operations on a large string using substr_replace consume lot of time, while using an alternative logic base on strings concatenations is almost instant. The following code will do 100 000 replacements operations on a string using two distinct logics. Both would produce identical result, but one will take only a few milliseconds while the other one will take almost 2 minutes. ```php <?php $pattern = "A basic string to repeat." . PHP_EOL; $multiplier = 100000; $string = str_repeat($pattern, $multiplier); $pattern_length = strlen($pattern); $search = "to repeat"; $search_pos = strpos($pattern, $search); $search_length = strlen($search); $replace = "repeated"; $replace_length = strlen($replace); $t1 = microtime(true); $result1 = ''; for ($i = 0; $i < $multiplier; $i ++) { $occurence_pos = $i * $pattern_length; $result1 .= substr($string, $occurence_pos, $search_pos); $result1 .= $replace; $result1 .= substr($string, $occurence_pos + $search_pos + $search_length, $pattern_length - $search_pos - $search_length); } $t2 = microtime(true); $result2 = $string; for ($i = 0; $i < $multiplier; $i ++) { $occurence_pos = $i * ($pattern_length - $search_length + $replace_length); $result2 = substr_replace($result2, $replace, $occurence_pos + $search_pos, $search_length); } $t3 = microtime(true); echo "Result size: " . number_format(strlen($result1) / 1000000, 2) . "MB" . PHP_EOL; echo "Identical result: " . ($result1 === $result2 ? "yes" : "no") . PHP_EOL; echo "Time using string concatenations: " . number_format($t2 - $t1, 2) . "s" . PHP_EOL; echo "Time using substr_replace: " . number_format($t3 - $t2, 2) . "s" . PHP_EOL; ``` Resulted in this output: ``` Result size: 2.50MB Identical result: yes Time using string concatenations: 0.03s Time using substr_replace: 117.15s ``` ### PHP Version 8.1.8 (cli) (built: Jul 12 2022 08:25:23) (NTS) ### Operating System Debian Bullseye docker image on Ubuntu 20.04

« previous php.bugs (#241920) next »