Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rtrim equal fast to preg_replace #13710

Closed
staabm opened this issue Mar 14, 2024 · 3 comments
Closed

rtrim equal fast to preg_replace #13710

staabm opened this issue Mar 14, 2024 · 3 comments

Comments

@staabm
Copy link
Contributor

staabm commented Mar 14, 2024

Description

I am currently doing some micro benchmarks and tried several things to speedup phpunit in some form.

one idea I had when looking at a hotpath of a app was to replace

$string = (string) preg_replace('#\d+$#', '', $name, -1, $count);

with

$string = rtrim($name, '0123456789')

I am wondering why a plain rtrim() is as fast as a preg_replace call which should have some kind of overhead for working with regex etc?

see

mstaab@mst22:/www/www$ hyperfine --warmup 10 'php preg.php' 'php rtrim.php'
Benchmark 1: php preg.php
  Time (mean ± σ):      56.9 ms ±   9.0 ms    [User: 30.6 ms, System: 25.7 ms]
  Range (min … max):    43.8 ms …  80.4 ms    41 runs

Benchmark 2: php rtrim.php
  Time (mean ± σ):      58.7 ms ±   9.2 ms    [User: 34.0 ms, System: 24.0 ms]
  Range (min … max):    43.8 ms …  83.0 ms    46 runs

Summary
  'php preg.php' ran
    1.03 ± 0.23 times faster than 'php rtrim.php'

mstaab@mst22:/www/www$ php -v
PHP 8.1.27 (cli) (built: Dec 21 2023 20:19:54) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.1.27, Copyright (c) Zend Technologies

mstaab@mst22:/www/www$ cat preg.php
<?php

$name = 'Sets redirect header on 301';

$string = (string) preg_replace('#\d+$#', '', $name, -1, $count);

mstaab@mst22:/www/www$ cat rtrim.php
<?php

$name = 'Sets redirect header on 301';

$string = rtrim($name, '0123456789');


PHP Version

8.1.27

Operating System

ubuntu22.04 lts

@damianwadley
Copy link
Member

Short answer: expressions like #\d+$# can be optimized fairly well, as the engine is able to recognize that it should start from the end of the string and look for digit characters. Which is essentially what rtrim is doing too.

@damianwadley damianwadley closed this as not planned Won't fix, can't repro, duplicate, stale Mar 14, 2024
@nielsdos
Copy link
Member

@staabm Your benchmarking is flawed. You're only doing a single call to rtrim vs preg_replace, so the execution time of that is drowned by the startup, parse+compile, and shutdown time of php. You need to do multiple loops. Furthermore, you're not testing on the latest development version (which does have performance improvements regarding function calls).

When testing with a modified script:

<?php
$name = 'Sets redirect header on 301';
for ($i=0;$i<500**2;$i++)
$string = (string) preg_replace('#\d+$#', '', $name, -1, $count);

and

<?php
$name = 'Sets redirect header on 301';
for ($i=0;$i<500**2;$i++)
$string = rtrim($name, '0123456789');

I get that rtrim is almost twice as fast:

Benchmark 1: ./sapi/cli/php regex.php
  Time (mean ± σ):      36.2 ms ±   0.8 ms    [User: 33.3 ms, System: 2.9 ms]
  Range (min … max):    35.1 ms …  39.6 ms    77 runs
 
Benchmark 2: ./sapi/cli/php rtrim.php
  Time (mean ± σ):      18.6 ms ±   0.6 ms    [User: 15.9 ms, System: 2.7 ms]
  Range (min … max):    17.6 ms …  20.7 ms    144 runs
 
Summary
  ./sapi/cli/php rtrim.php ran
    1.94 ± 0.08 times faster than ./sapi/cli/php regex.php

@staabm
Copy link
Contributor Author

staabm commented Mar 14, 2024

thats great news, thank you for the details - I was hoping for such a result, but was not able to prove it in benchmarks :).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants