4
\$\begingroup\$

I have the following piece of code:

$Page = str_replace('-&-', '-[+]-', $Page);
$Page = str_replace('&', '-[+]-', $Page);
$Page = str_replace('-and-', '-[+]-', $Page);
$Page = str_replace('-et-', '-[+]-', $Page);
$Page = str_replace('-und-', '-[+]-', $Page);
$Page = str_replace('-y-', '-[+]-', $Page);
$Page = str_replace('-&-', '-[+]-', $Page);

which I then run many times per page load (perhaps 10 to 40 times).

N.B. $Page represents a URL fragment - rarely more than 20 characters long.

Am I better off leaving it as it is, or may I, for the purposes of code maintenance, rewrite this code as:

$Page = preg_replace('/(-&-|-&-|&|-and-|-et-|-und-|-y-)/', '-[+]-', $Page);

without suffering a slowdown of one or several hundredths of a second?

(If the slowdown is a matter of milliseconds, I am less bothered).


Background:

I am less familiar with the evolution of PHP than with that of javascript, css etc. so when I see recommendations (long-stated, albeit from the late 2000s and early 2010s) like:

Avoid preg_replace unless you need to use it and always use str_replace instead, which is an order of magnitude faster.

I don't know if that recommendation still has any relevancy for PHP 7.3 in 2020, or whether that recommendation was important to follow in the days of PHP 5, but is less of a concern now (given that PHP 7 is so much faster and more optimised than its predecessor).

\$\endgroup\$
10
  • 1
    \$\begingroup\$ Oh dear. My first question on Code Review and downvoted already. Have I done something wrong? Is this the wrong sort of question for Code Review? Ta. I thought this sort of question was better to be asked here rather than over on Stack Overflow (?) \$\endgroup\$
    – Rounin
    Feb 1, 2020 at 11:24
  • \$\begingroup\$ I wish the could exaplain the vote \$\endgroup\$ Feb 1, 2020 at 11:47
  • 3
    \$\begingroup\$ The downvote my be because it reads as though you are asking about usage of a method, as opposed to an actual piece of code. If you are specifically concerned with the example you have given, then consider making that the focus of the question (since any feedback related to the code should be on-topic), or requesting a comparative review between the (concrete) examples. Stuff like "should I use X instead of Y" is simply not on-topic at Code Review: everything needs concrete context. \$\endgroup\$ Feb 1, 2020 at 11:58
  • \$\begingroup\$ Thanks. I have edited the question to make it clear that I am indeed asking about that specific piece of code (as well as questioning whether a piece of "common knowledge" relating to PHP performance is still accurate or now constitutes an old wive's tale). \$\endgroup\$
    – Rounin
    Feb 1, 2020 at 12:02
  • 1
    \$\begingroup\$ Is this question off-topic because: generic best practices are outside the scope of this site.? \$\endgroup\$ Feb 2, 2020 at 1:58

2 Answers 2

6
\$\begingroup\$

Most of such advises are crystal clear bullshit, on so many levels. You need to understand that such recommendations are never a result of some quality research, but just a rephrase of some vague rumor. The internet is full of chimpanzees.

This particular advise didn't make any sense even for PHP5.

That said, a set of consequent function calls apparently should be less efficient than a single call (but again if only it made any real life difference whatsoever).

That said, str_replace accepts array arguments, so it can be

$Page = str_replace(['-&-','-&-','&','-and-','-et-','-und-','-y-'], '-[+]-', $Page);

But you can use whatever version you like, as any difference is unnoticeable. Personally I find preg_replace() approach the cleanest and would prefer that.

As a rule of thumb, do not trust some random pieces of advise from Internet, especially performance-related. It's always just random rubbish. Bother with any optimizations only if your code actually has performance issues. And even in this case do not optimize random irrelevant parts but find the actual bottleneck and optimize it.

\$\endgroup\$
2
  • \$\begingroup\$ Thank you for an excellent and comprehensive answer. I didn't know that str_replace also accepts array arguments, so thanks for educating me on that, too. \$\endgroup\$
    – Rounin
    Feb 1, 2020 at 12:09
  • 1
    \$\begingroup\$ I ended up reading about chimpanzees and totally forgot what I was searching for... \$\endgroup\$ Apr 18, 2022 at 16:12
4
\$\begingroup\$

I am going to post my thoughts without using profanity or defame thousands of developers that I've never met. I hope this will not lessen the perceived value or correctness of this content.

First things first, I think it is important to know all of the viable tools at your disposal with php. Yes, str_replace() and preg_replace() are the two widely used replacing functions, but do you also know about strtr()? Through my own experiences supporting other developers in the Stack Exchange Network, it is clear to me that strtr() is a lesser known/used function. For the exact case that you have provided, it does not enjoy the most concise syntax, but it does make a single pass through the input string (like your piped preg_replace() call). This function has a special/useful behavior in that it will never replace replacements - this is sometimes an issue with the other two functions mentioned here. The truth is: due to the fact that your process has no risk of replacing replacements, the other functions are both adequate tools. You have done well to order &amp after -&-.

Before I go any further, I will state my complete agreement with YCS about his advised solution. I would be using a single str_replace() call with an array of search strings. Assuming your project does not require word boundaries/lookarounds, case-sensitivity, or multibyte support, str_replace() is going to behave reliably and accurately.

So how do you choose what is the best tool for your project? Well...

  1. Do you fully understand the coding technique and the fringe cases that may arise? Copy-pasting code that you don't understand will lead to a project that you cannot confidently maintain. If you understand it now, but might not later that is what comments / docblocks are for. When in doubt, read the php docs; when you have time, read the upvoted comments.

  2. What is the scope/usage of the technique? If the data being processed is relatively small, is not iterated, and is not likely to be extended/expanded, then performance may never be an issue -- so toiling with benchmark tests will be a waste of dev time.

    If there is any chance that the input data will be relatively large, that the process will be executed in a loop, or that the data may grow in size as your application matures, then you are going to want to pay a sensible amount of attention to performance.

  3. Do you (or your dev team or your supervisor) have a preconceived bias against regular expressions? Some people may laugh at this one, but it happens because of maintainability (see #1). When I use regular expressions in a team build and I know other members on the team do not have the same level of understanding that I do, I will include demo links from 3v4l.org and/or regex101.com so that other devs can understand the intricacies when maintenance is required.

  4. Let's not forget one of the golden rules of string manipulation: do not use regex unless there is a clear and valuable benefit. The documentation is not telling lies -- str_replace() will always outperform with the same data. So make educated and purposeful choices and give future developers reason to be confident in your scripting abilities -- you might even inspire someone.

p.s. your regex doesn't need a capture group, so you can safely remove the parentheses.

\$\endgroup\$
1
  • \$\begingroup\$ Thank you for this well-thought-out response. As recommended, I have adopted str_replace() using an array of search strings as my approach. \$\endgroup\$
    – Rounin
    Feb 3, 2020 at 9:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.