php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #81243 Too much memory is allocated for the return value of preg_replace
Submitted: 2021-07-11 08:14 UTC Modified: 2021-09-06 17:45 UTC
From: abecker at mailbox dot org Assigned: cmb (profile)
Status: Closed Package: PCRE related
PHP Version: 8.0.8 OS: Linux
Private report: No CVE-ID: None
 [2021-07-11 08:14 UTC] abecker at mailbox dot org
Description:
------------
The string returned by preg_replace uses too much memory - multiples of the actual string size in bytes. For big strings, this can be a significant performance issue.

mb_ereg_replace does not have this problem.

When I copy the returned string using some of the PHP string functions, the storage size is reduced in case the memory for the string is reallocated.

Test script:
---------------
$base_memory = memory_get_usage();
$test_string = str_repeat('Eins zwei drei', 2000);
var_dump(memory_get_usage() - $base_memory);
$replaced = preg_replace('/\s/', '-', $test_string);
var_dump(memory_get_usage() - $base_memory);
$replaced = str_repeat($replaced, 1);
#$replaced = str_replace('e', 'e', $replaced);
#$replaced = $replaced[0] . substr($replaced, 1);
var_dump(memory_get_usage() - $base_memory);


Expected result:
----------------
int(28672)
int(57728)
int(57728)

Actual result:
--------------
int(28672)
int(106880)
int(57728)


Patches

Add a Patch

Pull Requests

Pull requests:

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2021-07-12 11:25 UTC] cmb@php.net
-Assigned To: +Assigned To: cmb
 [2021-07-12 11:25 UTC] cmb@php.net
The following pull request has been associated:

Patch Name: Fix #81243: Too much memory is allocated for preg_replace()
On GitHub:  https://github.com/php/php-src/pull/7231
Patch:      https://github.com/php/php-src/pull/7231.patch
 [2021-07-12 16:39 UTC] git@php.net
Automatic comment on behalf of cmb69
Revision: https://github.com/php/php-src/commit/a6b43086e6799eedf02d36ccea103e2b10c1005a
Log: Fix #81243: Too much memory is allocated for preg_replace()
 [2021-07-12 16:39 UTC] git@php.net
-Status: Assigned +Status: Closed
 [2021-09-06 17:02 UTC] nospam at briat dot org
Since this fix preg_replace seems much slower (up to 100 times).

I notice by debuging the https://www.drupal.org/project/advagg module for Drupal 7 which use this cssmin.php v2.4.8-4. By using xdebug profiler I discover that  this lib uses intensively preg_replace which use 99% of the total time.

I made small script that call the lib and compress a css file, here's the total time in seconds with the two version of PHP.

docker run -it --rm --name my-running-script -v "$PWD":/usr/src/myapp -w /usr/src/myapp php:7.4.11-cli-alpine  php test.php
0.19343304634094s

docker run -it --rm --name my-running-script -v "$PWD":/usr/src/myapp -w /usr/src/myapp php:7.4.12-cli-alpine  php test.php
11.722915887833s
 [2021-09-06 17:13 UTC] cmb@php.net
Thanks for reporting!  Since the commit has already shipped (PHP
7.4.22 and 8.0.9), please open a new bug ticket, so we can
properly track the regression.
 [2021-09-06 17:45 UTC] nikic@php.net
It would be great if you could also share the script you're benchmarking (or some reduced version).
 [2021-09-07 17:12 UTC] nospam at briat dot org
I open the issue #81424. It could also be relarted to the PCRE version.
 
PHP Copyright © 2001-2021 The PHP Group
All rights reserved.
Last updated: Fri Sep 17 21:03:38 2021 UTC