[php-src] Issue #9003: Bad performances on substr_replace on large strings
| From: | cedric-anne | 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