[wp-trac] [WordPress Trac] #62692: Performance regression for get_option in 6.4
WordPress Trac
noreply at wordpress.org
Fri Dec 13 20:09:22 UTC 2024
#62692: Performance regression for get_option in 6.4
--------------------------+-----------------------------
Reporter: rmccue | Owner: (none)
Type: defect (bug) | Status: new
Priority: normal | Milestone: Awaiting Review
Component: Cache API | Version: 6.4
Severity: major | Keywords:
Focuses: performance |
--------------------------+-----------------------------
In 6.4, `get_option()` was changed to pull individual items from the
object cache before checking `notoptions` as a performance optimisation
(#58277).
Before this change, calling `get_option( 'notexist' )` would do the
following:
1. On the first call, it would check `notoptions` (and load this from the
external cache if not set).
2. If not set in `notoptions`, it would check the individual cache key for
the option (`wp_cache_get( 'notexist', 'options' )`), and add it to
`notoptions`
3. On the second call, it would check `notoptions` and return early.
This meant that subsequent calls would only check the static `notoptions`
which would likely be loaded into memory.
After this change, calling `get_option( 'notexist' )` would do the
following:
1. On ''every'' call, check the individual cache key for the option
(`wp_cache_get( 'notexist', 'options' )`)
2. If not set, ''then'' check `notoptions`
3. On the second call, check the individual cache key ''again''
This would seem like an optimization - in the original, it was noted that
the common case is a cache hit, so this should be better. However, this
misses two important pieces of information.
Firstly, `notoptions` is a single entry for the entire page, and
''always'' exists - this means caches will store this in memory and
generate at most 1 external request to the cache.
Secondly, not all object caches implement an internal cache of ''misses''.
Notably, the popular wp-redis drop-in [https://github.com/pantheon-systems
/wp-redis/blob/c4e59718f69b9640e88443b3a8a48884fc8a678d/object-
cache.php#L732-L742 does not]. Even if they did, this would still be worse
for performance, since `notoptions` is a single get across the entire
request.
We experienced this with an enterprise customer who upgraded recently, and
this caused a massive increase in load on their caching servers
(saturating the network links), as they have a large number of cache
misses. (They have sparse options stored across a multisite network.)
This original change should be reverted.
To replicate this, call `get_option( 'notexist' )` in a loop. Prior to
6.4, this would generate 2 total cache gets; after 6.4, it generates an
infinite number, as each iteration of the cycle triggers a cache get which
misses.
--
Ticket URL: <https://core.trac.wordpress.org/ticket/62692>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform
More information about the wp-trac
mailing list