<?php

function pure_regex() {
	$result = preg_replace('/\G(?:^|(?(?<!^.).)..(?:.{4})*?)\Kr/s', 'M', 'it is a test string.');
}
function with_callback() {
	$result = preg_replace_callback(['/^./', '/.{3}\K./'], function ($m) {
         return $m[0] == 'r' ? 'M' : $m[0];
       }, 'it is a test string.');
}
function no_regex() {
    $str ='it is a test string.';
	$len = strlen($str);
	if($str[0]=='r') $str[0] = 'M';
	for($i=3; $i<$len; $i+=4)
	  if($str[$i] == 'r')
	    $str[$i] = 'M';
}
function regex_array() {
	$result = preg_replace(['/^r/', '/\G(?:.{3}[^r])*+.{3}\Kr/s'], 'M', 'it is a test string.');
}

$best = 999999999;
$worst = 0;
$best_num = -1;
function speed_test($code, $loops = 500000) {
	$before = microtime(true);
	for ($i=0 ; $i<$loops ; $i++) {
	    $code();
	}
	$after = microtime(true);
	$delay = $after-$before;
	return $delay;
}

// --------

$names = ['with_callback', 'regex_array', 'no_regex', 'pure_regex'];
$loops = 50000;

foreach ($names as $code_num => $f)
{
	$delay = speed_test($f, $loops);
	if ($delay < $best) {
		$best = $delay;
		$best_num = $code_num;
	}
	if ($delay > $worst) {
		$worst = $delay;
	}
	echo 'Code #' . ($code_num + 1) . "($names[$code_num]): \t" . number_format($delay, 3) . " secs/" . $loops/1E3 . "k loops\n";
}
echo "BEST: $names[$best_num] by " . number_format((1- $best / $worst) * 100, 0) . "% over worst case";

?>