PHP str_replace performance

Here I have 2 methods that use str_replaceto replace strings in a given phrase.

// Method 1
$phrase  = "You should eat fruits, vegetables, and fiber every day.";
$healthy = array("fruits", "vegetables", "fiber");
$yummy   = array("pizza", "beer", "ice cream");
$phrase = str_replace($healthy, $yummy, $phrase);

// Method 2
$phrase  = "You should eat fruits, vegetables, and fiber every day.";
$phrase = str_replace("fruits", "pizza", $phrase);
$phrase = str_replace("vegetables", "beer", $phrase);
$phrase = str_replace("fiber", "ice cream", $phrase);

Which method is more efficient (in terms of runtime and resources)?

Suppose that the real phrase is much longer (for example, 50,000 characters), and the words to replace have a lot more pairs.

I think method 2 calls str_replace3 times, which will cost more function calls; on the other hand, method 1 creates 2 arrays, and str_replacemust parse 2 arrays at runtime.

+5
source share
4 answers

1 . 1 , : . 2 .

<?php
$time_start = microtime(true);
for($i=0;$i<=1000000;$i++){
    // Method 1
    $phrase  = "You should eat fruits, vegetables, and fiber every day.";
    $healthy = array("fruits", "vegetables", "fiber");
    $yummy   = array("pizza", "beer", "ice cream");
    $phrase = str_replace($healthy, $yummy, $phrase);
}
$time_end = microtime(true);
$time = $time_end - $time_start;
echo "Did Test 1 in ($time seconds)\n<br />";



$time_start = microtime(true);
for($i=0;$i<=1000000;$i++){
    // Method2
    $phrase  = "You should eat fruits, vegetables, and fiber every day.";
    $phrase = str_replace("fruits", "pizza", $phrase);
    $phrase = str_replace("vegetables", "beer", $phrase);
    $phrase = str_replace("fiber", "ice cream", $phrase);

}
$time_end = microtime(true);
$time = $time_end - $time_start;
echo "Did Test 2 in ($time seconds)\n";
?>  

1 (3.6321988105774 )

2 (2.8234610557556 )


: , 50 ., ajreal, .
<?php
$phrase  = str_repeat("You should eat fruits, vegetables, and fiber every day.",50000);
$healthy = array("fruits", "vegetables", "fiber");
$yummy   = array("pizza", "beer", "ice cream");

$time_start = microtime(true);
for($i=0;$i<=10;$i++){
    // Method 1
    $phrase = str_replace($healthy, $yummy, $phrase);
}
$time_end = microtime(true);
$time = $time_end - $time_start;
echo "Did Test 1 in ($time seconds)\n<br />";



$time_start = microtime(true);
for($i=0;$i<=10;$i++){
    // Method2
    $phrase = str_replace("fruits", "pizza", $phrase);
    $phrase = str_replace("vegetables", "beer", $phrase);
    $phrase = str_replace("fiber", "ice cream", $phrase);

}
$time_end = microtime(true);
$time = $time_end - $time_start;
echo "Did Test 2 in ($time seconds)\n";
?>  

1 (1.1450328826904 )

2 (1.3119208812714 )

+5

, .

:

" , , 3 , 2, .

$phrase = " , ."; 3 : 1 (4.3436799049377 ) 2 (5.7581660747528 ) 3 (7.5069718360901 ) "

        <?php
        $time_start = microtime(true);

        $healthy = array("fruits", "vegetables", "fiber");
        $yummy   = array("pizza", "beer", "ice cream");

        for($i=0;$i<=1000000;$i++){
            // Method 1
            $phrase  = "You should eat fruits, vegetables, and fiber every day.";
            $phrase = str_replace($healthy, $yummy, $phrase);
        }
        $time_end = microtime(true);
        $time = $time_end - $time_start;
        echo "Did Test 1 in ($time seconds)<br /><br />";



        $time_start = microtime(true);
        for($i=0;$i<=1000000;$i++){
            // Method2
            $phrase  = "You should eat fruits, vegetables, and fiber every day.";
            $phrase = str_replace("fruits", "pizza", $phrase);
            $phrase = str_replace("vegetables", "beer", $phrase);
            $phrase = str_replace("fiber", "ice cream", $phrase);

        }
        $time_end = microtime(true);
        $time = $time_end - $time_start;
        echo "Did Test 2 in ($time seconds)<br /><br />";




        $time_start = microtime(true);
        for($i=0;$i<=1000000;$i++){
                foreach ($healthy as $k => $v) {
                  if (strpos($phrase, $healthy[$k]) === FALSE)  
                  unset($healthy[$k], $yummy[$k]);
                }                                          
                if ($healthy) $new_str = str_replace($healthy, $yummy, $phrase);

        }
        $time_end = microtime(true);
        $time = $time_end - $time_start;
        echo "Did Test 3 in ($time seconds)<br /><br />";

        ?>  

1 (3.5785729885101 )

2 (3.8501658439636 )

3 (0.13844394683838 )

+3

@djot,

<?php
     foreach ($healthy as $k => $v) {
        if (strpos($phrase, $healthy[$k]) === FALSE)  
             unset($healthy[$k], $yummy[$k]);
        }  

/ 4

<?php 
 $time_start = microtime(true);

        $healthy = array("fruits", "vegetables", "fiber");
        $yummy   = array("pizza", "beer", "ice cream");

        for($i=0;$i<=1000000;$i++){
            // Method 1
            $phrase  = "You should eat fruits, vegetables, and fiber every day.";
            $phrase = str_replace($healthy, $yummy, $phrase);
        }
        $time_end = microtime(true);
        $time = $time_end - $time_start;
        echo "Did Test 1 in ($time seconds)". PHP_EOL. PHP_EOL;



        $time_start = microtime(true);
        for($i=0;$i<=1000000;$i++){
            // Method2
            $phrase  = "You should eat fruits, vegetables, and fiber every day.";
            $phrase = str_replace("fruits", "pizza", $phrase);
            $phrase = str_replace("vegetables", "beer", $phrase);
            $phrase = str_replace("fiber", "ice cream", $phrase);

        }
        $time_end = microtime(true);
        $time = $time_end - $time_start;
        echo "Did Test 2 in ($time seconds)" . PHP_EOL. PHP_EOL;




        $time_start = microtime(true);
        for($i=0;$i<=1000000;$i++){
            $a = $healthy;
            $b = $yummy;
                foreach ($healthy as $k => $v) {
                  if (strpos($phrase, $healthy[$k]) === FALSE)  
                  unset($a[$k], $b[$k]);
                }                                          
                if ($a) $new_str = str_replace($a, $b, $phrase);

        }
        $time_end = microtime(true);
        $time = $time_end - $time_start;
        echo "Did Test 3 in ($time seconds)". PHP_EOL. PHP_EOL;



        $time_start = microtime(true);
        for($i=0;$i<=1000000;$i++){
            $ree = false;
            foreach ($healthy as $k) {
              if (strpos($phrase, $k) !== FALSE)  { //something to replace
                  $ree = true;
                  break;
              }
            }                                          
            if ($ree === true) {
                $new_str = str_replace($healthy, $yummy, $phrase);
            }
        }
        $time_end = microtime(true);
        $time = $time_end - $time_start;
        echo "Did Test 4 in ($time seconds)". PHP_EOL. PHP_EOL;

1 (0,38219690322876 )

2 (0.42352104187012 )

3 (0.47777700424194 )

4 (0.19691610336304 )

+1

, OP :

, (, 50 000 ) .

, ( ) , preg_replace_callback, , .

Here is a common function, which in my case with a string of 1.5Mb and ~ 20,000 pairs of replacements was about 10 times faster, although due to the need to split partitions into pieces due to too large “regular expressions” errors could have (in my particular case it was impossible, however).

In my particular case, I was able to optimize this to about a 100-fold increase in performance because my search strings matched a specific pattern. (PHP version 7.1.11 on a 32-bit version of Windows 7).

function str_replace_bulk($search, $replace, $subject, &$count = null) {
  // Assumes $search and $replace are equal sized arrays
  $lookup = array_combine($search, $replace);
  $result = preg_replace_callback(
    '/' .
      implode('|', array_map(
        function($s) {
          return preg_quote($s, '/');
        },
        $search
      )) .
    '/',
    function($matches) use($lookup) {
      return $lookup[$matches[0]];
    },
    $subject,
    -1,
    $count
  );
  if (
    $result !== null ||
    count($search) < 2 // avoid infinite recursion on error
  ) {
    return $result;
  }
  // With a large number of replacements (> ~2500?), 
  // PHP bails because the regular expression is too large.
  // Split the search and replacements in half and process each separately.
  // NOTE: replacements within replacements may now occur, indeterminately.
  $split = (int)(count($search) / 2);
  error_log("Splitting into 2 parts with ~$split replacements");
  $result = str_replace_bulk(
    array_slice($search, $split),
    array_slice($replace, $split),
    str_replace_bulk(
      array_slice($search, 0, $split),
      array_slice($replace, 0, $split),
      $subject,
      $count1
    ),
    $count2
  );
  $count = $count1 + $count2;
  return $result;
}
0
source

All Articles