Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Potherca/b9db0801cc0257715361361c9a05ec78 to your computer and use it in GitHub Desktop.
Save Potherca/b9db0801cc0257715361361c9a05ec78 to your computer and use it in GitHub Desktop.
Benchmarks for the comparison of various styles of writing a `clamp` function in PHP

📝 This text is part of the article Comparison of various styles of writing a clamp function in PHP

Summary

Benchmarks were created using PhpBench counting in units of μs(1).

The final result was:

mean subject description
20.035 μs 832B9C44 return min max
23.376 μs CAB599E9 if/return, elseif/return, else/return
23.538 μs A13E087E if/return, if/return, return (shorthand)
23.595 μs 8389C469 if, elseif, return
23.723 μs 60AA891E return/ternary/ternary
23.985 μs 83C742FF if/return, if/return, return
24.089 μs 7BC1F85B if, if, return;

Steps taken

The following steps were taken in order to benchmark the clamp variations:

  1. Create a benchmark class
  2. Run phpbench
  3. Combine the result from the 3 scenario's
  4. Sort the results

Each step is described in detail below.

1. Create a benchmark class

I create a class that held a separate method for each variation. Each variation was fed data for 3 separate scenario's:

  1. A value within the min/max range
  2. A value above the min/max range
  3. A value below the min/max range

The source code can be seen in the BenchmarkClamp.php file.

2. Run phpbench

PhpBench was run using the following command:

phpbench  run ./BenchmarkClamp.php  --iterations=15 --revs=1000 --retry-threshold=5 --report='generator: "table", cols: [ "subject", "params", "mean", "diff" ], break: ["benchmark"], sort: {subject: "asc", mean: "desc"}'

This gives the following results:

7 subjects, 315 iterations, 21,000 revs, 0 rejects
(best [mean mode] worst) = 19.098 [23.192 23.167] 20.588 (μs)
⅀T: 7,305.424μs μSD/r 0.408μs μRSD/r: 1.761%
benchmark: BenchmarkClamp

+----------------+------------+----------+---------+
| subject        | params     | mean     | diff    |
+----------------+------------+----------+---------+
| bench_60AA891E | [20,10,30] | 23.944μs | +19.98% |
| bench_60AA891E | [30,10,20] | 23.657μs | +18.54% |
| bench_60AA891E | [10,20,30] | 23.569μs | +18.10% |
| bench_7BC1F85B | [30,10,20] | 24.395μs | +22.24% |
| bench_7BC1F85B | [20,10,30] | 24.335μs | +21.94% |
| bench_7BC1F85B | [10,20,30] | 23.538μs | +17.95% |
| bench_832B9C44 | [30,10,20] | 20.188μs | +1.16%  |
| bench_832B9C44 | [10,20,30] | 19.961μs | +0.02%  |
| bench_832B9C44 | [20,10,30] | 19.957μs | 0.00%   |
| bench_8389C469 | [30,10,20] | 23.668μs | +18.60% |
| bench_8389C469 | [20,10,30] | 23.581μs | +18.16% |
| bench_8389C469 | [10,20,30] | 23.537μs | +17.94% |
| bench_83C742FF | [10,20,30] | 24.324μs | +21.89% |
| bench_83C742FF | [20,10,30] | 23.890μs | +19.71% |
| bench_83C742FF | [30,10,20] | 23.742μs | +18.97% |
| bench_A13E087E | [10,20,30] | 23.752μs | +19.02% |
| bench_A13E087E | [30,10,20] | 23.513μs | +17.82% |
| bench_A13E087E | [20,10,30] | 23.349μs | +17.00% |
| bench_CAB599E9 | [20,10,30] | 23.678μs | +18.65% |
| bench_CAB599E9 | [30,10,20] | 23.317μs | +16.84% |
| bench_CAB599E9 | [10,20,30] | 23.135μs | +15.93% |
+----------------+------------+----------+---------+

3. Combine the results

Combining the result-sets for the 3 separate scenario's, we get:

subject mean
832B9C44 (20.188 + 19.961 + 19.957)/3 = 20.0353333
CAB599E9 (23.678 + 23.317 + 23.135)/3 = 23.3766667
A13E087E (23.752 + 23.513 + 23.349)/3 = 23.5380000
8389C469 (23.668 + 23.581 + 23.537)/3 = 23.5953333
60AA891E (23.944 + 23.657 + 23.569)/3 = 23.7233333
83C742FF (24.324 + 23.890 + 23.742)/3 = 23.9853333
7BC1F85B (24.395 + 24.335 + 23.538)/3 = 24.0893333

4. Sort the results

Translating this back to each variation this gives us:

mean subject description
20.0353333 μs 832B9C44 return min max
23.3766667 μs CAB599E9 if/return, elseif/return, else/return
23.5380000 μs A13E087E if/return, if/return, return (shorthand)
23.5953333 μs 8389C469 if, elseif, return
23.7233333 μs 60AA891E return/ternary/ternary
23.9853333 μs 83C742FF if/return, if/return, return
24.0893333 μs 7BC1F85B if, if, return;

Footnotes

  1. one millionth of a second
<?php
namespace Potherca\Example;
/**
* Benchmark the separate `clamp` functions.
*/
class BenchmarkClamp
{
/**
* @ParamProviders({"provideValues"})
*/
public function bench_7BC1F85B($value, $min, $max)
{
if ($value < $min) {
$value = $min;
}
if ($value > $max) {
$value = $max;
}
return $value;
}
/**
* @ParamProviders({"provideValues"})
*/
public function bench_83C742FF($value, $min, $max)
{
if ($value < $min) {
return $min;
}
if ($value > $max) {
return $max;
}
return $value;
}
/**
* @ParamProviders({"provideValues"})
*/
public function bench_832B9C44($value, $min, $max)
{
return min($max, max($min, $value));
}
/**
* @ParamProviders({"provideValues"})
*/
public function bench_8389C469($value, $min, $max)
{
if ($value < $min) {
$value = $min;
} elseif ($value > $max) {
$value = $max;
}
return $value;
}
/**
* @ParamProviders({"provideValues"})
*/
public function bench_CAB599E9($value, $min, $max)
{
if ($value < $min) {
return $min;
} elseif ($value > $max) {
return $max;
} else {
return $value;
}
}
/**
* @ParamProviders({"provideValues"})
*/
public function bench_60AA891E($value, $min, $max)
{
return $value < $min ? $min : ( $value > $max ? $max : $value );
}
/**
* @ParamProviders({"provideValues"})
*/
public function bench_A13E087E($value, $min, $max)
{
if ($value < $min) return $min;
if ($value > $max) return $max;
return $value;
}
/**
* Provides data for 3 separate scenario's
*
* @return array
*/
public function provideValues()
{
return [
'above range' => [30, 10, 20],
'beneath range' => [10, 20, 30],
'within range' => [20, 10, 30],
];
}
}
/*EOF*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment