Page MenuHomePhabricator

Use strtr instead of str_replace when possible
Closed, DeclinedPublic

Description

Author: theevilipaddress

Description:
The PHP function strtr is like 4 times faster than str_replace and would be pretty useful to use in MediaWiki in many places.

In the source code, I've noticed many replacements of underscores to spaces and vice versa, often in the form str_replace("_", " ", $foo), whereas strtr($foo, "_", " ") is much faster.


Version: unspecified
Severity: enhancement
URL: http://php.net/manual/en/function.strtr.php

Details

Reference
bz26605

Event Timeline

bzimport raised the priority of this task from to Medium.Nov 21 2014, 11:14 PM
bzimport set Reference to bz26605.
bzimport added a subscriber: Unknown Object (MLST).

Is there any proof of this performance gain? (Benchmarks or alike)

Is it in all cases, or only some?

reedy@ubuntu64-esxi:~/mediawiki/trunk/phase3/maintenance/benchmarks$ php bench_strtr_str_replace.php
100 times: function bench_strtr_str_replace->benchstrtr() :

0.22ms (  0.00ms each)

100 times: function bench_strtr_str_replace->benchstr_replace() :

0.24ms (  0.00ms each)

I'm not sure if that's worthwhile enough a gain...?

r79755

I did some tweaks to the benchmark in r79854; results on my test box (MacBook Pro, 2.4GHz Core 2 Duo, Mac OS X 10.6.6, 64-bit PHP 5.3.4 built via MacPorts) with 10,000 reps:

$ php bench_strtr_str_replace.php --count=10000
10000 times: function bench_strtr_str_replace->benchstrtr() :
19.67ms ( 0.00ms each)
10000 times: function bench_strtr_str_replace->benchstr_replace() :
22.05ms ( 0.00ms each)
10000 times: function bench_strtr_str_replace->benchstrtr_indirect() :
22.53ms ( 0.00ms each)
10000 times: function bench_strtr_str_replace->benchstr_replace_indirect() :
26.29ms ( 0.00ms each)

It takes at least 3000 reps to make a 1ms difference in execution time, so it's not likely to make a big performance difference to make this change.

But -- as happy coincidence, the difference in execution time is about the same as the difference from adding a level of function-call indirection. This means that replacing the str_replace() calls with calls to a nice global function, and having it use strtr, would have almost no performance impact, but would allow for changing the underscore/space normalization rules globally MUCH more easily.

So, if you *are* inclined to go changing all those bits, I'd recommend encapsulating them in a nice function and concentrating on how it makes maintenance and customization easier.

I got different result where indirect calls are both slower:

$ php bench_strtr_str_replace.php --count=10000
10000 times: function bench_strtr_str_replace->benchstrtr() :

57.79ms (  0.01ms each)

10000 times: function bench_strtr_str_replace->benchstr_replace() :

58.82ms (  0.01ms each)

10000 times: function bench_strtr_str_replace->benchstrtr_indirect() :

73.34ms (  0.01ms each)

10000 times: function bench_strtr_str_replace->benchstr_replace_indirect() :

75.39ms (  0.01ms each)

On a Macbook Air ( 1.7 GHz Intel Core i5 ) with Mac OS X 10.7.2 PHP:
$ php -version
PHP 5.3.6 with Suhosin-Patch (cli) (built: Sep 8 2011 19:34:00)
Copyright (c) 1997-2011 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2011 Zend Technologies

with Xdebug v2.1.2, Copyright (c) 2002-2011, by Derick Rethans

$

A nice function will probably makes code nicer though.

Krinkle set Security to None.
Krinkle removed a subscriber: Unknown Object (MLST).
Krinkle subscribed.

These two functions have different charactistics. Neither of them is logically or unconditionally bad.

For 99% of cases, they both do the same, and are very fast.

If performance is an with a specific case, that should be reported by itself. A mass-replace would have high risk and likely no reward whatsoever.