Skip to content

Instantly share code, notes, and snippets.

@dtakken
Last active January 16, 2020 14:53
Show Gist options
  • Save dtakken/1539d64170921363dc8d1ed62effcd45 to your computer and use it in GitHub Desktop.
Save dtakken/1539d64170921363dc8d1ed62effcd45 to your computer and use it in GitHub Desktop.
Benchmarking script for measuring type check cache performance, based on https://gist.github.com/dstogov/fb32023e8dd55e58312ae0e5029556a9#file-union_bench-php
<?php
class A {
}
class B {
}
class C {
}
class Foo {
static public $static_prop = 42;
static public A|B|C $class_union_static_prop;
public A|B|C $class_union_prop;
}
class D extends C {
}
class E extends D {
}
class F extends E {
}
function func1($x) {
return $x + 1;
}
function simple_func($n) {
for ($i = 0; $i < $n; $i++)
func1(42);
}
function simple_static_prop($n) {
for ($i = 0; $i < $n; $i++)
Foo::$static_prop = $i;
}
function class_union_static_prop($n) {
$c = new C;
for ($i = 0; $i < $n; $i++)
Foo::$class_union_static_prop = $c;
}
function simple_prop($n) {
$o = new Foo;
for ($i = 0; $i < $n; $i++) {
$o->prop = $i;
}
unset($o);
}
function class_union_prop($n) {
$o = new Foo;
$c = new C;
for ($i = 0; $i < $n; $i++) {
$o->class_union_prop = $c;
}
unset($o);
}
function func7($o) {
return is_object($o);
}
function no_hint($n) {
$o = new A;
for ($i = 0; $i < $n; $i++) {
func7($o);
}
unset($o);
}
function func8(?A $o) {
return is_object($o);
}
function class_hint($n) {
$o = new A;
for ($i = 0; $i < $n; $i++) {
func8($o);
}
unset($o);
}
function func9a(A|B|C|null $o) {
return is_object($o);
}
function func9c(C|A|B|null $o) {
return is_object($o);
}
function func9d($o): A|B|C|null {
return $o;
}
function union_hint1($n) {
$o = new A;
for ($i = 0; $i < $n; $i++) {
func9a($o);
}
unset($o);
}
function union_hint2($n) {
$o = new C;
for ($i = 0; $i < $n; $i++) {
func9a($o);
}
unset($o);
}
function union_hint3($n) {
$o = new D;
for ($i = 0; $i < $n; $i++) {
func9a($o);
}
unset($o);
}
function union_hint4($n) {
$o = new E;
for ($i = 0; $i < $n; $i++) {
func9a($o);
}
unset($o);
}
function union_hint5($n) {
$o = null;
for ($i = 0; $i < $n; $i++) {
func9c($o);
}
unset($o);
}
function union_hint6($n) {
$o = new F;
for ($i = 0; $i < $n; $i++) {
func9a($o);
}
unset($o);
}
function union_hint7($n) {
$o = new A;
for ($i = 0; $i < $n; $i++) {
func9d($o);
}
unset($o);
}
function union_hint8($n) {
$o = new C;
for ($i = 0; $i < $n; $i++) {
func9d($o);
}
unset($o);
}
function union_hint9($n) {
$o = new D;
for ($i = 0; $i < $n; $i++) {
func9d($o);
}
unset($o);
}
function union_hint10($n) {
$o = new E;
for ($i = 0; $i < $n; $i++) {
func9d($o);
}
unset($o);
}
function union_hint11($n) {
$o = new F;
for ($i = 0; $i < $n; $i++) {
func9d($o);
}
unset($o);
}
/*****/
function empty_loop($n) {
for ($i = 0; $i < $n; ++$i) {
}
}
function gethrtime()
{
$hrtime = hrtime();
return (($hrtime[0]*1000000000 + $hrtime[1]) / 1000000000);
}
function start_test()
{
ob_start();
return gethrtime();
}
function end_test($start, $name, $overhead = null)
{
global $total;
global $last_time;
$end = gethrtime();
ob_end_clean();
$last_time = $end-$start;
$total += $last_time;
$num = number_format($last_time,3);
$pad = str_repeat(" ", 40-strlen($name)-strlen($num));
if (is_null($overhead)) {
echo $name.$pad.$num."\n";
} else {
$num2 = number_format($last_time - $overhead,3);
echo $name.$pad.$num." ".$num2."\n";
}
ob_start();
return gethrtime();
}
function total()
{
global $total;
$pad = str_repeat("-", 40);
echo $pad."\n";
$num = number_format($total,3);
$pad = str_repeat(" ", 40-strlen("Total")-strlen($num));
echo "Total".$pad.$num."\n";
}
const N = 50_000_000;
$t0 = $t = start_test();
empty_loop(N);
$t = end_test($t, 'empty_loop');
$overhead = $last_time;
simple_static_prop(N);
$t = end_test($t, 'Foo::$static_prop = ...', $overhead);
class_union_static_prop(N);
$t = end_test($t, 'Foo::$class_union_static_prop = ...', $overhead);
simple_prop(N);
$t = end_test($t, '$o->prop = ...', $overhead);
class_union_prop(N);
$t = end_test($t, '$o->class_union_prop = ...', $overhead);
simple_func(N);
$t = end_test($t, 'func($x)', $overhead);
no_hint(N);
$t = end_test($t, 'func($obj)', $overhead);
union_hint5(N);
$t = end_test($t, 'func(A|B|C|null $obj) (null)', $overhead);
union_hint1(N);
$t = end_test($t, 'func(A|B|C|null $obj) (A)', $overhead);
union_hint2(N);
$t = end_test($t, 'func(A|B|C|null $obj) (C)', $overhead);
union_hint3(N);
$t = end_test($t, 'func(A|B|C|null $obj) (D)', $overhead);
union_hint4(N);
$t = end_test($t, 'func(A|B|C|null $obj) (E)', $overhead);
union_hint6(N);
$t = end_test($t, 'func(A|B|C|null $obj) (F)', $overhead);
union_hint7(N);
$t = end_test($t, 'func($obj): A|B|C|null (A)', $overhead);
union_hint8(N);
$t = end_test($t, 'func($obj): A|B|C|null (C)', $overhead);
union_hint9(N);
$t = end_test($t, 'func($obj): A|B|C|null (D)', $overhead);
union_hint10(N);
$t = end_test($t, 'func($obj): A|B|C|null (E)', $overhead);
union_hint11(N);
$t = end_test($t, 'func($obj): A|B|C|null (F)', $overhead);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment