Skip to content

Instantly share code, notes, and snippets.

@thekid
Created August 29, 2018 15:41
Show Gist options
  • Select an option

  • Save thekid/41c9086eb91f3c8aeee801492892e585 to your computer and use it in GitHub Desktop.

Select an option

Save thekid/41c9086eb91f3c8aeee801492892e585 to your computer and use it in GitHub Desktop.
What's the fastest implementation of a map lookup on types?
<?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));
@thekid
Copy link
Author

thekid commented Aug 29, 2018

$ 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, null

The 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, null

The version with eval and ifs:

$ xp typemap.script.php if
[email protected](124) : eval()'d code(54) : eval()'d code000002413C4F272A {
}
Person  : 1000000 iterations, 0.088 seconds, "objects"
Value   : 1000000 iterations, 0.122 seconds, "objects"
This    : 1000000 iterations, 0.116 seconds, null

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment