|
<?php |
|
|
|
define('REPEAT_BENCH', 4); |
|
define('REPEAT_EXEC', 5); |
|
|
|
function array_merge_sorted($first, $second) |
|
{ |
|
$out = []; |
|
for ( |
|
$f = 0, $s = 0, |
|
$firstLength = count($first), |
|
$secondLength = count($second); |
|
$f < $firstLength || $s < $secondLength; |
|
) { |
|
if (!isset($first[$f])) { |
|
$out[] = $second[$s]; |
|
++$s; |
|
} elseif (!isset($second[$s])) { |
|
$out[] = $first[$f]; |
|
++$f; |
|
} elseif ($first[$f] > $second[$s]) { |
|
$out[] = $second[$s]; |
|
++$s; |
|
} else { |
|
$out[] = $first[$f]; |
|
++$f; |
|
} |
|
} |
|
return $out; |
|
} |
|
|
|
function merge_ordered($a, $b) { |
|
// let a will be longest array |
|
$aLen = count($a); |
|
$bLen = count($b); |
|
$resultLen = $aLen + $bLen; |
|
$result = new SplFixedArray($resultLen); |
|
for( |
|
$i = 0, $aIdx=0, $bIdx=0; |
|
$i < $resultLen; |
|
$i++ |
|
) { |
|
if ($aIdx === $aLen || ($bIdx < $bLen && $a[$aIdx] > $b[$bIdx])) { |
|
$result[$i] = $b[$bIdx++]; |
|
} else { |
|
$result[$i] = $a[$aIdx++]; |
|
} |
|
} |
|
|
|
return $result; |
|
} |
|
|
|
|
|
function merge_ordered3($a, $b) { |
|
// let a will be longest array |
|
$aLen = count($a); |
|
$bLen = count($b); |
|
$resultLen = $aLen + $bLen; |
|
$result = new SplFixedArray($resultLen); |
|
for( |
|
$i = 0, $aIdx=0, $bIdx=0; |
|
$i < $resultLen; |
|
$i++ |
|
) { |
|
if ($aIdx === $aLen || ($bIdx < $bLen && $a[$aIdx] > $b[$bIdx])) { |
|
$result[$i] = $b[$bIdx++]; |
|
} else { |
|
$result[$i] = $a[$aIdx++]; |
|
} |
|
} |
|
|
|
return $result->toArray(); |
|
} |
|
|
|
function merge_ordered2($a, $b) { |
|
// let a will be longest array |
|
$aLen = count($a); |
|
$bLen = count($b); |
|
$resultLen = $aLen + $bLen; |
|
$result = []; |
|
for( |
|
$i = 0, $aIdx=0, $bIdx=0; |
|
$i < $resultLen; |
|
$i++ |
|
) { |
|
if ($aIdx === $aLen || ($bIdx < $bLen && $a[$aIdx] > $b[$bIdx])) { |
|
$result[] = $b[$bIdx++]; |
|
} else { |
|
$result[] = $a[$aIdx++]; |
|
} |
|
} |
|
|
|
return $result; |
|
} |
|
|
|
function native_merge($a, $b) { |
|
$r = array_merge($a, $b); |
|
sort($r); |
|
return $r; |
|
} |
|
|
|
function benchmark($description, $callback) { |
|
$averageExecutionTime = 0; |
|
$minExecutionTime = PHP_INT_MAX; |
|
$maxExecutionTime = 0; |
|
|
|
for($i = 0;$i<REPEAT_BENCH;$i++) { |
|
$executionTime = 0; |
|
for($j = 0;$j < REPEAT_EXEC;$j++) { |
|
$executionTime += $callback(); |
|
} |
|
$executionTime /= REPEAT_EXEC; |
|
if ($executionTime > $maxExecutionTime) { |
|
$maxExecutionTime = $executionTime; |
|
} |
|
|
|
if ($executionTime < $minExecutionTime) { |
|
$minExecutionTime = $executionTime; |
|
} |
|
|
|
$averageExecutionTime += $executionTime; |
|
} |
|
$averageExecutionTime /= REPEAT_BENCH; |
|
|
|
echo sprintf("%s:\n-----------------\n", $description); |
|
echo sprintf("Average execution time: %d ms\n", $averageExecutionTime*1000); |
|
echo sprintf("Min execution time: %d ms\n", $minExecutionTime*1000); |
|
echo sprintf("Max execution time: %d ms\n\n", $maxExecutionTime*1000); |
|
} |
|
|
|
echo "Generating test data..."; |
|
$a = range(2, 1000000, 2); |
|
$b = range(2, 2000000, 4); |
|
echo " done.\n\n"; |
|
|
|
benchmark('Try implementation with SplFixedArray', function () use ($a, $b) { |
|
$t = microtime(true); |
|
merge_ordered($a, $b); |
|
return microtime(true) - $t; |
|
}); |
|
|
|
benchmark('Try implementation with SplFixedArray with toArray', function () use ($a, $b) { |
|
$t = microtime(true); |
|
merge_ordered3($a, $b); |
|
return microtime(true) - $t; |
|
}); |
|
|
|
benchmark('Try implementation with simple arrays', function () use ($a, $b) { |
|
$t = microtime(true); |
|
merge_ordered2($a, $b); |
|
return microtime(true) - $t; |
|
}); |
|
|
|
benchmark('Tyranron method', function () use ($a, $b) { |
|
$t = microtime(true); |
|
array_merge_sorted($a, $b); |
|
return microtime(true) - $t; |
|
}); |
|
|
|
benchmark('array_merge + sort', function () use ($a, $b) { |
|
$t = microtime(true); |
|
native_merge($a, $b); |
|
return microtime(true) - $t; |
|
}); |