Speed up WP_Object_Cache::_exists()
|Reported by:||nacin||Owned by:||nacin|
Description (last modified by nacin)
Both kurtpayne and I have noticed that the _exists() method is way slower than it should be. It only contains three PHP functions: isset(), is_array(), and array_key_exists(). Yet frequently, I see 5-10% of a pageload spent in cache.php, and somewhere around 30-40% of that spent in _exists() (so > 2% overall).
In this one example, _exists() was called 2507 times, so every little bit counts. 2295 of them came from get(), 212 from add(). It is therefore quite obvious that we rely heavily on our local cache.
Based on that assumption, we can make some changes to speed up this conditional:
isset( $this->cache[$group] ) && is_array( $this->cache[$group] ) && array_key_exists( $key, $this->cache[$group] );
First, the is_array() can go. Never would the $group key exist with the value of anything other than an array, and cache.php makes this assumption elsewhere.
isset() is mighty fast for a language construct, while arrays in PHP are generally slow. The next step would be to remove array_key_exists(), but we need to do so without regressing #20004.
So, we can pre-empty array_key_exists() with an isset() check first. If the key is set (and not null), then we can return true immediately. Otherwise, we call array_key_exists() to see if the key is actually null.
Technically slower for null or not-at-all-set keys, but faster when the key is set. And it is only slower by a simple isset(), which is fast.
isset( $this->cache[ $group ] ) && ( isset( $this->cache[ $group ][ $key ] ) || array_key_exists( $key, $this->cache[ $group ] ) );
array_key_exists() went from being called all 2500 times, to only 192 times, and the time cost of _exists() drops to 10% of what it was. (Time cost 97000 to 9300.) Total time spent in cache.php falls by a third.