6

Looking at the Pimple source code I found that it is storing objects and their ids in two different arrays:

class Container implements \ArrayAccess
{
    private $values = array();
    ...
    private $keys = array();
}

And then:

public function offsetSet($id, $value)
{
    ...
    $this->values[$id] = $value;
    $this->keys[$id] = true;
}

And finally:

public function offsetGet($id)
{
    if (!isset($this->keys[$id])) {
        throw new \InvalidArgumentException(sprintf('Identifier "%s" is not defined.', $id));
    }
}

I've also seen something similar in Phalcon source code here.

My question is why to store object id key separately, why not just if (!isset($this->values[$id]))? Is it faster to search within an array? I did some tests and it seems that search speed is pretty the same.

UnderDog
  • 305
  • 1
  • 4
  • 14
Kanstantsin K.
  • 512
  • 4
  • 17
  • 2
    Among other things, `$this->values[$id]` can have a value of `NULL`, and this will still identify that it exists, because `$this->keys[$id]` is true – Mark Baker Sep 09 '15 at 15:22
  • 3
    why not use `array_key_exists` ? – cmorrissey Sep 09 '15 at 15:29
  • And what about Phalcon code: https://github.com/phalcon/cphalcon/blob/master/phalcon/acl/adapter/memory.zep#L174-L175 ? – Kanstantsin K. Sep 09 '15 at 15:29
  • 1
    Well `array_key_exists()` has the overhead of a function call, where `isset()` doesn't because it's a control structure, so possibly optimising for testing speed at the expense of setting speed and memory.... I'm offering suggestions, but don't actually know what was in the minds of the developers when they made this decision – Mark Baker Sep 09 '15 at 15:37
  • 1
    `isset()` is much more efficient than `array_key_exists()`. See this [benchmark](https://secure.php.net/manual/en/function.array-key-exists.php#107786) – doydoy44 Sep 09 '15 at 16:23
  • @doydoy44 I like the solution given in that benchmark `if (isset(...) || array_key_exists(...)){` ill defiantly be implementing this in my projects – cmorrissey Sep 09 '15 at 18:32
  • @cmorrissey: I like too. :) – doydoy44 Sep 09 '15 at 18:51
  • 1
    This was done for performance reasons. Check out [this commit](https://github.com/silexphp/Pimple/commit/c94869c7396d1617f6191435f0f5828cec40b036) – mTorres Sep 10 '15 at 06:18

1 Answers1

1

Ok, it seems like when the array entry value may be null you have to check key existence with an array_key_exists() function. However, this is several times slower than isset(), so having keys in the separate array makes possible to use isset(). But the better way would be if (isset(...) || array_key_exists(...)), that has almost the same speed as simple isset(), but eliminates the need of separate array for keys tracking (thanks, @doydoy44).

Kanstantsin K.
  • 512
  • 4
  • 17