[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