Skip to content

Embed URL

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
arrayof-perf.md

Arrayof Performance

<?php
function arrayof_foo(Foo[] $fooze) {
    foreach ($fooze as $foo) {
        $foo->bar();
    }
}

function user_instanceof_foo(array $fooze) {
    foreach ($fooze as $foo) {
        if ($foo instanceof Foo) {
            $foo->bar();
        }
    }
}

function user_filter_foo(array $fooze) {
    foreach (array_filter($fooze, function ($object) {
        return $object instanceof Foo;
    }) as $foo) {
        $foo->bar();
    }
}

function user_arrays(array $arrays) {
    foreach ($arrays as $array) {
        if (is_array($array)) {
            continue;
        }
    }
}

function arrayof_arrays(array[] $arrays) {
    foreach ($arrays as $array) {
        continue;
    }
}

function user_callables(array $callables) {
    foreach ($callables as $callable) {
        if (is_callable($callable)) {
            $callable();
        }
    }
}

function arrayof_callables(callable[] $callables) {
    foreach ($callables as $callable) {
        $callable();
    }
}

function user_interfaces(ArrayOfFoo $fooArray) {
    foreach ($fooArray as $i => $foo) {
        $foo->bar();
    }
}

abstract class ArrayOf implements ArrayAccess, Iterator, Countable {
    protected $type = null;

    protected $data = [];

    protected $index = 0;

    public function __construct() {
        if (is_null($this->type)) { throw new Exception('Extending classes must specify a type.'); }
    }

    public function offsetSet($offset, $value) {
        if ($value instanceof $this->type) {
            $this->data[$offset] = $value;
        } else {
            $type = is_object($value) ? get_class($value) : gettype($value);
            throw new UnexpectedValueException(
                sprintf('Value must be of type %s, %s given.', $this->type, $type)
            );
        }
    }

    public function offsetExists($offset) { return isset($this->data[$offset]); }
    public function offsetGet($offset) { return $this->data[$offset]; }
    public function offsetUnset($offset) { unset($this->data[$offset]); }
    public function current() { return $this->data[$this->index]; }
    public function next() { ++$this->index; }
    public function key() { return $this->index; }
    public function valid() { return isset($this->data[$this->index]); }
    public function rewind() { $this->index = 0; }
    public function count() { return count($this->data); }
}
class ArrayOfFoo extends ArrayOf { protected $type = 'Foo'; }
class Foo { public function bar() { return __METHOD__; } }

$ctors = [];
$timers = [];
$fooze = [];
$arrays = [];
$callables = [];
$result = [];

$max = $argv[1] ? $argv[1] : 1000;

$start = microtime(true);
while (count($fooze) < $max) {
    $fooze[] = new Foo();
}
$ctors["native"] = microtime(true)-$start;

while (count($arrays) < $max) {
    $arrays[] = array();
    $callables[] = function(){};
}

$start = microtime(true);
$fooArray = new ArrayOfFoo; 
for ($i=0; count($fooArray) < $max; $i++) {
    $fooArray[$i] = new Foo;
}
$ctors["user"] = microtime(true)-$start;

$totalRuns = 500;
$timers = [
    "user_instanceof_foo" => $fooze,
    "user_filter_foo" => $fooze,
    "arrayof_foo" => $fooze,
    "user_arrays" => $arrays,
    "arrayof_arrays" => $arrays,
    "user_callables" => $callables,
    "arrayof_callables" => $callables,
    "user_interfaces" => $fooArray
];

for($i = 0; $i < $totalRuns; ++$i){
    foreach($timers as $callable => $arg){
        $alpha = microtime(true);
        $callable($arg);
        $result[$callable] += microtime(true) - $alpha;
    }
}

$result = array_map(function ($v) use($totalRuns) {
    return $v / $totalRuns;
}, $result);

asort($result, SORT_NUMERIC);
asort($ctors, SORT_NUMERIC);

printf("constructors [not very reliable timings]:\n");
foreach ($ctors as $name => $time) {
    printf("%-30s\t%.8f\n", $name, $time);
}
printf("\n");
printf("tests:\n");
foreach ($result as $name => $time) {
    printf("%-30s\t%.8f\n", 
        str_replace("_", " ", $name), $time);
}
?>

Note: each test function is run 500 times, averages provided

[joe@fiji php-src]$ sapi/cli/php -n -dmemory_limit=2G perf.php 10
constructors [not very reliable timings]:
native                          0.00001502
user                            0.00003695

tests:
arrayof arrays                  0.00000122
arrayof callables               0.00000202
user arrays                     0.00000209
arrayof foo                     0.00000223
user instanceof foo             0.00000227
user callables                  0.00000275
user filter foo                 0.00000468
user interfaces                 0.00000835

[joe@fiji php-src]$ sapi/cli/php -n -dmemory_limit=2G perf.php 100
constructors [not very reliable timings]:
native                          0.00004292
user                            0.00014400

tests:
arrayof arrays                  0.00000708
arrayof callables               0.00001340
user arrays                     0.00001344
arrayof foo                     0.00001379
user instanceof foo             0.00001475
user callables                  0.00002122
user filter foo                 0.00003038
user interfaces                 0.00006573

[joe@fiji php-src]$ sapi/cli/php -n -dmemory_limit=2G perf.php 1000
constructors [not very reliable timings]:
native                          0.00034094
user                            0.00122619

tests:
arrayof arrays                  0.00007181
arrayof foo                     0.00013031
user arrays                     0.00013081
arrayof callables               0.00013340
user instanceof foo             0.00014088
user callables                  0.00020693
user filter foo                 0.00028824
user interfaces                 0.00066317

[joe@fiji php-src]$ sapi/cli/php -n -dmemory_limit=2G perf.php 10000
constructors [not very reliable timings]:
native                          0.00346088
user                            0.01473308

tests:
arrayof arrays                  0.00235372
arrayof foo                     0.00243142
user arrays                     0.00320780
arrayof callables               0.00378044
user callables                  0.00433458
user filter foo                 0.00465060
user instanceof foo             0.00549773
user interfaces                 0.00862223

[joe@fiji php-src]$ sapi/cli/php -n -dmemory_limit=2G perf.php 100000
constructors [not very reliable timings]:
native                          0.03715611
user                            0.18054104

tests:
arrayof foo                     0.03434128
user arrays                     0.03928255
arrayof arrays                  0.04027043
arrayof callables               0.05607406
user filter foo                 0.05802278
user callables                  0.05824624
user instanceof foo             0.06152818
user interfaces                 0.13526678
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.