Make WordPress Core

Opened 2 years ago

Closed 2 years ago

Last modified 2 years ago

#21320 closed enhancement (fixed)

Speed up WP_Object_Cache::_exists()

Reported by: nacin Owned by: nacin
Milestone: 3.5 Priority: normal
Severity: normal Version: 3.4
Component: Cache API Keywords:
Focuses: Cc:

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.

End result:

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.

Change History (3)

comment:1 nacin2 years ago

  • Owner set to nacin
  • Resolution set to fixed
  • Status changed from new to closed

In [21285]:

Improve the performance of WP_Object_Cache's _exists() method.

Results showed a performance improvement on one admin screen of 90ms (~2%).

fixes #21320. see #20004.

comment:2 nacin2 years ago

  • Description modified (diff)

Worth noting that I shouldn't have used an absolute unit in [21285] — profiling obviously slows down a page (the page does *not* take 4.5 seconds to compute normally), so these numbers are, of course, only good for relative comparisons.

comment:3 kurtpayne2 years ago

  • Cc kpayne@… added
Note: See TracTickets for help on using tickets.