Created
August 29, 2018 15:41
-
-
Save thekid/41c9086eb91f3c8aeee801492892e585 to your computer and use it in GitHub Desktop.
What's the fastest implementation of a map lookup on types?
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php namespace typemap; | |
| use lang\Value; | |
| use lang\reflect\Package; | |
| use util\Objects; | |
| use util\cmd\Console; | |
| use util\data\unittest\fixtures\Person; | |
| use util\profiling\Timer; | |
| class ForeachMap { | |
| private $types= []; | |
| public function __construct() { | |
| foreach (Package::forName('util.data.unittest.fixtures')->getClassNames() as $t) { | |
| $this->types[literal($t)]= 'objects'; | |
| } | |
| $this->types[Value::class]= 'objects'; | |
| } | |
| public function marshaller($instance) { | |
| foreach ($this->types as $type => $marshaller) { | |
| if ($instance instanceof $type) { | |
| return $marshaller; | |
| } | |
| } | |
| return null; | |
| } | |
| } | |
| class IssetForeachMap { | |
| private $types= []; | |
| public function __construct() { | |
| foreach (Package::forName('util.data.unittest.fixtures')->getClassNames() as $t) { | |
| $this->types[literal($t)]= 'objects'; | |
| } | |
| $this->types[Value::class]= 'objects'; | |
| } | |
| public function marshaller($instance) { | |
| $c= get_class($instance); | |
| if (isset($this->types[$c])) return $this->types[$c]; | |
| foreach ($this->types as $type => $marshaller) { | |
| if ($instance instanceof $type) { | |
| return $marshaller; | |
| } | |
| } | |
| return null; | |
| } | |
| } | |
| abstract class IfMap { | |
| public static function new() { | |
| $code= ''; | |
| foreach (Package::forName('util.data.unittest.fixtures')->getClassNames() as $t) { | |
| $code.= 'if ($instance instanceof '.literal($t).') return "objects"; '; | |
| } | |
| return eval('return new class() extends '.self::class.' { | |
| public function marshaller($instance) { | |
| '.$code.' | |
| if ($instance instanceof '.Value::class.') return "objects"; | |
| return null; | |
| } | |
| };'); | |
| } | |
| } | |
| switch ($argv[1]) { | |
| case 'foreach': $m= new ForeachMap(); break; | |
| case 'isset': $m= new IssetForeachMap(); break; | |
| case 'if': $m= IfMap::new(); | |
| } | |
| // Setup | |
| $t= new Timer(); | |
| $person= new Person(6100, getenv('USER')); | |
| $value= new class() implements Value { | |
| public function toString() { return 'value'; } | |
| public function hashCode() { return spl_object_hash($this); } | |
| public function compareTo($value) { return $value === $this ? 0 : 1; } | |
| }; | |
| Console::writeLine($m); | |
| // Mapped | |
| $t->start(); | |
| for ($i= 0; $i < 1000000; $i++) { | |
| $r= $m->marshaller($person); | |
| } | |
| $t->stop(); | |
| Console::writeLinef('Person : %d iterations, %.3f seconds, %s', $i, $t->elapsedTime(), Objects::stringOf($r)); | |
| // Interface | |
| $t->start(); | |
| for ($i= 0; $i < 1000000; $i++) { | |
| $r= $m->marshaller($value); | |
| } | |
| $t->stop(); | |
| Console::writeLinef('Value : %d iterations, %.3f seconds, %s', $i, $t->elapsedTime(), Objects::stringOf($r)); | |
| // Unmapped | |
| $t->start(); | |
| for ($i= 0; $i < 1000000; $i++) { | |
| $r= $m->marshaller($this); | |
| } | |
| $t->stop(); | |
| Console::writeLinef('This : %d iterations, %.3f seconds, %s', $i, $t->elapsedTime(), Objects::stringOf($r)); |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
$ xp typemap.script.php foreach typemap.ForeachMap { typemap\ForeachMaptypes => [ util\data\unittest\fixtures\Activity => "objects" util\data\unittest\fixtures\People => "objects" util\data\unittest\fixtures\Person => "objects" util\data\unittest\fixtures\PersonWithoutConstructor => "objects" lang\Value => "objects" ] } Person : 1000000 iterations, 0.500 seconds, "objects" Value : 1000000 iterations, 0.731 seconds, "objects" This : 1000000 iterations, 0.748 seconds, nullThe version with a shortcut if a direct match exists:
$ xp typemap.script.php isset typemap.IssetForeachMap { typemap\IssetForeachMaptypes => [ util\data\unittest\fixtures\Activity => "objects" util\data\unittest\fixtures\People => "objects" util\data\unittest\fixtures\Person => "objects" util\data\unittest\fixtures\PersonWithoutConstructor => "objects" lang\Value => "objects" ] } Person : 1000000 iterations, 0.157 seconds, "objects" Value : 1000000 iterations, 0.834 seconds, "objects" This : 1000000 iterations, 0.833 seconds, nullThe version with eval and ifs: