3v4l.org

run code in 300+ PHP versions simultaneously
<?php class A { } class B { public $a; public function __construct(A $a) { $this->a = $a; } } class C { public $b; public function __construct(B $b) { $this->b = $b; } } class D { public $c; public function __construct(C $c) { $this->c = $c; } } class E { public $d; public function __construct(D $d) { $this->d = $d; } } class F { public $e; public function __construct(E $e) { $this->e = $e; } } class G { public $f; public function __construct(F $f) { $this->f = $f; } } class H { public $g; public function __construct(G $g) { $this->g = $g; } } class I { public $h; public function __construct(H $h) { $this->h = $h; } } class J { public $i; public function __construct(I $i) { $this->i = $i; } } class K { public $j; public function __construct(K $k) { $this->k = $k; } } class Dice { private $rules = []; private $cache = []; private $instances = []; public function addRule($name, Rule $rule) { $this->rules[ltrim($name, '\\')] = $rule; } public function getRule($name) { if (isset($this->rules[ltrim($name, '\\')])) return $this->rules[ltrim($name, '\\')]; foreach ($this->rules as $key => $rule) { if ($rule->instanceOf === null && $key !== '*' && is_subclass_of($name, $key) && $rule->inherit === true) return $rule; } return isset($this->rules['*']) ? $this->rules['*'] : new Rule; } public function create($component, array $args = [], $forceNewInstance = false) { if (!$forceNewInstance && isset($this->instances[$component])) return $this->instances[$component]; if (!isset($this->cache[$component])) { $rule = $this->getRule($component); $class = new \ReflectionClass(empty($rule->instanceOf) ? $component : $rule->instanceOf); $constructor = $class->getConstructor(); $params = $constructor ? $this->getParams($constructor, $rule) : null; $this->cache[$component] = function($args, $forceNewInstance) use ($component, $rule, $class, $constructor, $params) { if ($rule->shared) { if ($constructor) { try { $this->instances[$component] = $object = $class->newInstanceWithoutConstructor(); $constructor->invokeArgs($object, $params($args)); } catch (\ReflectionException $r) { $this->instances[$component] = $object = $class->newInstanceArgs($params($args)); } } else { $this->instances[$component] = $object = $class->newInstanceWithoutConstructor(); } } else $object = $params ? $class->newInstanceArgs($params($args)) : new $class->name; if (!empty($rule->call)) foreach ($rule->call as $call) $class->getMethod($call[0])->invokeArgs($object, call_user_func($this->getParams($class->getMethod($this->expand($call[0])), new Rule), $call[1])); return $object; }; } return $this->cache[$component]($args, $forceNewInstance); } private function expand($param, array $share = []) { if (is_array($param)) return array_map(function($p) use($share) { return $this->expand($p, $share); }, $param); if ($param instanceof Instance) return $this->create($param->name, $share); else if (is_callable($param)) return $param($this); return $param; } private function getParams(\ReflectionMethod $method, Rule $rule) { $subs = empty($rule->substitutions) ? null :$rule->substitutions; $paramClasses = []; foreach ($method->getParameters() as $param) $paramClasses[] = $param->getClass() ? $param->getClass()->name : null; return function($args) use ($paramClasses, $rule, $subs) { $share = empty($rule->shareInstances) ? [] : array_map([$this, 'create'], $rule->shareInstances); if (!empty($share) || !empty($rule->constructParams)) $args = array_merge($args, $this->expand($rule->constructParams, $share), $share); $parameters = []; foreach ($paramClasses as $class) { if (!empty($args)) for ($i = 0; $i < count($args); $i++) { if ($class && $args[$i] instanceof $class) { $parameters[] = array_splice($args, $i, 1)[0]; continue 2; } } if (!empty($subs) && isset($subs[$class])) $parameters[] = is_string($subs[$class]) ? $this->create($subs[$class]) : $this->expand($subs[$class]); else if (!empty($class)) $parameters[] = $this->create($class, $share, !empty($rule->newInstances) && in_array(strtolower($class), array_map('strtolower', $rule->newInstances))); else if (!empty($args)) $parameters[] = array_shift($args); } return $parameters; }; } } class Rule { public $shared = false; public $constructParams = []; public $substitutions = []; public $newInstances = []; public $instanceOf; public $call = []; public $inherit = true; public $shareInstances = []; } class Instance { public $name; public function __construct($instance) { $this->name = $instance; } } class Dice2 { private $rules = []; private $cache = []; private $instances = []; public function addRule($name, Rule $rule) { $this->rules[ltrim($name, '\\')] = $rule; } public function getRule($name) { if (isset($this->rules[ltrim($name, '\\')])) return $this->rules[ltrim($name, '\\')]; foreach ($this->rules as $key => $rule) { if ($rule->instanceOf === null && $key !== '*' && is_subclass_of($name, $key) && $rule->inherit === true) return $rule; } return isset($this->rules['*']) ? $this->rules['*'] : new Rule; } public function create($component, array $args = [], $forceNewInstance = false) { if (!$forceNewInstance && isset($this->instances[$component])) return $this->instances[$component]; if (!isset($this->cache[$component])) { $rule = $this->getRule($component); $class = new \ReflectionClass(empty($rule->instanceOf) ? $component : $rule->instanceOf); $constructor = $class->getConstructor(); $params = $constructor ? $this->getParams($constructor, $rule) : null; $this->cache[$component] = function($args, $forceNewInstance) use ($component, $rule, $class, $constructor, $params) { if ($rule->shared) { $this->instances[$component] = $object = $class->isInternal() && $constructor ? $class->newInstanceArgs($params($args)) : $class->newInstanceWithoutConstructor(); if ($constructor && !$class->isInternal()) $constructor->invokeArgs($object, $params($args)); } else $object = $params ? new $class->name(...$params($args)) : new $class->name; if (!empty($rule->call)) foreach ($rule->call as $call) $class->getMethod($call[0])->invokeArgs($object, call_user_func($this->getParams($class->getMethod($this->expand($call[0])), new Rule), $call[1])); return $object; }; } return $this->cache[$component]($args, $forceNewInstance); } private function expand($param, array $share = []) { if (is_array($param)) return array_map(function($p) use($share) { return $this->expand($p, $share); }, $param); if ($param instanceof Instance) return $this->create($param->name, $share); else if (is_callable($param)) return $param($this); return $param; } private function getParams(\ReflectionMethod $method, Rule $rule) { $subs = empty($rule->substitutions) ? null :$rule->substitutions; $paramClasses = []; foreach ($method->getParameters() as $param) $paramClasses[] = $param->getClass() ? $param->getClass()->name : null; return function($args) use ($paramClasses, $rule, $subs) { $share = empty($rule->shareInstances) ? [] : array_map([$this, 'create'], $rule->shareInstances); if (!empty($share) || !empty($rule->constructParams)) $args = array_merge($args, $this->expand($rule->constructParams, $share), $share); $parameters = []; foreach ($paramClasses as $class) { if (!empty($args)) for ($i = 0; $i < count($args); $i++) { if ($class && $args[$i] instanceof $class) { $parameters[] = array_splice($args, $i, 1)[0]; continue 2; } } if (!empty($subs) && isset($subs[$class])) $parameters[] = is_string($subs[$class]) ? $this->create($subs[$class]) : $this->expand($subs[$class]); else if (!empty($class)) $parameters[] = $this->create($class, $share, !empty($rule->newInstances) && in_array(strtolower($class), array_map('strtolower', $rule->newInstances))); else if (!empty($args)) $parameters[] = array_shift($args); } return $parameters; }; } } $dice1 = new Dice; $dice2 = new Dice2; $j1 = $dice1->create('J'); $j2 = $dice2->create('J'); $t1 = microtime(true); for ($i = 0; $i < 10000; $i++) { $j = $dice1->create('J'); } $t2 = microtime(true); echo 'dice1: ' . ($t2 - $t1) . "\n\n"; $t1 = microtime(true); for ($i = 0; $i < 10000; $i++) { $j = $dice2->create('J'); } $t2 = microtime(true); echo 'dice1: ' . ($t2 - $t1) . "\n\n";

Here you find the average performance (time & memory) of each version. A grayed out version indicates it didn't complete successfully (based on exit-code).

VersionSystem time (s)User time (s)Memory (MiB)
7.4.00.0100.22014.85
7.3.120.0030.30514.68
7.3.110.0100.23115.01
7.3.100.0060.21514.98
7.3.90.0030.23614.83
7.3.80.0070.20915.11
7.3.70.0100.19215.03
7.3.60.0070.25615.06
7.3.50.0030.20315.00
7.3.40.0100.18514.91
7.3.30.0030.21414.89
7.3.20.0030.21916.66
7.3.10.0160.19416.72
7.3.00.0030.23616.48
7.2.250.0070.34315.47
7.2.240.0030.26515.17
7.2.230.0030.25615.30
7.2.220.0000.26415.44
7.2.210.0030.25315.02
7.2.200.0030.23015.33
7.2.190.0030.24515.30
7.2.180.0060.25515.38
7.2.170.0070.28615.07
7.2.00.0070.13019.46
7.1.330.0070.31315.84
7.1.320.0070.33815.78
7.1.310.0030.36915.65
7.1.300.0030.38115.82
7.1.290.0000.30215.70
7.1.280.0030.30515.98
7.1.270.0030.33215.81
7.1.260.0100.29915.91
7.1.70.0000.16017.08
7.1.60.0070.19319.40
7.1.50.0070.20417.00
7.1.00.0030.29322.36
7.0.200.0070.16116.89
7.0.140.0000.30022.07
7.0.120.0030.30722.04
7.0.110.0000.30722.09
7.0.100.0070.28322.16
7.0.90.0070.29722.06
7.0.80.0070.29722.16
7.0.70.0030.29322.07
7.0.60.0000.30322.15
7.0.50.0000.30722.13
7.0.40.0070.30022.12
7.0.30.0030.29022.15
7.0.20.0100.27021.98
7.0.10.0030.30322.05
7.0.00.0030.29022.04
5.6.280.0000.56021.23
5.6.260.0070.50321.19
5.6.250.0100.50021.20
5.6.240.0030.48720.95
5.6.230.0100.49721.20
5.6.220.0030.51320.89
5.6.210.0070.47721.17
5.6.200.0070.49020.95
5.6.190.0000.50320.87
5.6.180.0000.51020.92
5.6.170.0070.49721.00
5.6.160.0000.50321.13
5.6.150.0070.50021.08
5.6.140.0000.49021.04
5.6.130.0030.50021.05
5.6.120.0030.51320.86
5.6.110.0070.50321.19
5.6.100.0000.51021.03
5.6.90.0070.50320.89
5.6.80.0000.50320.43
5.6.70.0070.49320.47
5.6.60.0030.50020.35
5.6.50.0000.49020.35
5.6.40.0030.50020.55
5.6.30.0000.50020.53
5.6.20.0000.49020.41
5.6.10.0030.50020.51
5.6.00.0070.49320.54
5.5.380.0000.07317.77
5.5.370.0070.06317.68
5.5.360.0070.07317.63
5.5.350.0030.07017.61
5.5.340.0000.07318.28
5.5.330.0100.06318.03
5.5.320.0030.07018.10
5.5.310.0030.07318.26
5.5.300.0030.07318.19
5.5.290.0030.07318.22
5.5.280.0070.07318.22
5.5.270.0030.07718.12
5.5.260.0030.07318.09
5.5.250.0130.06317.91
5.5.240.0070.06717.64
5.5.230.0070.06717.61
5.5.220.0030.06717.53
5.5.210.0100.06317.41
5.5.200.0030.06717.58
5.5.190.0000.07017.38
5.5.180.0000.07717.38
5.5.160.0030.07017.61
5.5.150.0030.07017.57
5.5.140.0100.06317.61
5.5.130.0070.06717.51
5.5.120.0030.06717.36
5.5.110.0030.06717.30
5.5.100.0070.06717.48
5.5.90.0030.06717.53
5.5.80.0000.05017.31
5.5.70.0030.07017.34
5.5.60.0030.06717.52
5.5.50.0070.06317.24
5.5.40.0030.06317.24
5.5.30.0070.06317.47
5.5.20.0000.07317.52
5.5.10.0030.06017.52
5.5.00.0000.06317.39
5.4.450.0030.07319.42
5.4.440.0070.07019.45
5.4.430.0000.07719.49
5.4.420.0070.06719.41
5.4.410.0030.07019.23
5.4.400.0000.07019.20
5.4.390.0030.07019.13
5.4.380.0030.06719.00
5.4.370.0070.06319.00
5.4.360.0070.06319.05
5.4.350.0000.07319.16
5.4.340.0030.05019.25
5.4.320.0000.07319.04
5.4.310.0070.06719.19
5.4.300.0070.06718.95
5.4.290.0030.06719.15
5.4.280.0000.06718.95
5.4.270.0000.07019.00
5.4.260.0000.06019.00
5.4.250.0000.07318.99
5.4.240.0030.06719.34
5.4.230.0070.06719.23
5.4.220.0030.06719.35
5.4.210.0030.06019.04
5.4.200.0030.06318.98
5.4.190.0000.07019.18
5.4.180.0000.07019.14
5.4.170.0070.05719.18
5.4.160.0070.06319.02
5.4.150.0070.07019.00
5.4.140.0030.06016.43
5.4.130.0030.06716.42
5.4.120.0030.06316.58
5.4.110.0030.06716.36
5.4.100.0070.06316.48
5.4.90.0000.06316.57
5.4.80.0030.06316.57
5.4.70.0070.06016.55
5.4.60.0070.06016.29
5.4.50.0030.06316.68
5.4.40.0030.06016.50
5.4.30.0000.06316.39
5.4.20.0030.06016.67
5.4.10.0030.06716.44
5.4.00.0030.06316.02

preferences:
34.95 ms | 400 KiB | 5 Q