-
Notifications
You must be signed in to change notification settings - Fork 130
Description
Overview
- Proposed module name: Optimized Autoloaded Options
- Proposed module slug: optimized-autoloaded-options
- Proposed module owner GitHub username(s): markjaquith, felixarntz
This module proposal was created during WordCamp US 2022 as a collaboration between @merkys7 @markjaquith @felixarntz @sabrina-zeidan @rytisder.
About the module
WordPress has basically forever had a mechanism to load many (likely most) of its options in one single database request, by relying on a single flag autoload
which could be set to yes
or no
. This is being done to improve performance, since having individual database queries for every option used on a page would be a lot slower.
However, the decision whether to autoload
an option is currently left to plugins and themes (when they call add_option()
or update_option()
), without making it a requirement: There is a default value of yes
, and many (likely most) plugin and theme developers are not aware of what that value does or that it even exists.
This often results in an extremely bloated list of options to autoload, with many of these options unused, especially over time as plugins are tried out and then deleted, replaced with other plugins etc. As of today there is no mechanism in core to clean up any of this.
Purpose
The primary goal of the proposed module is to keep the list of options to autoload at a sizable level, to make the relevant database request faster and to avoid the scenario where the list of those options and values is too large to fit into an object cache solution.
Developers of plugins and themes should no longer be responsible for this as this is a very low level problem that WordPress core can solve by itself better than offloading it to each individual extension. Additionally, if this was based on an API, it would be unlikely or at least take years (if not decades) that plugins and themes would use such an API correctly at scale.
Scope
The module would do the following to achieve the above goal:
- Track which options are actually used on the site and based on that regularly rebuild the list of options to autoload, by dynamically modifying the
autoload
column in the database.- This routine would hook into get_option() calls to keep track of used options within a request.
- It would be periodically restarted, so that it does not just grow forever (since one of the goals explicitly to clear out old “junk”).
- It would only be started when there is a logged in user with sufficient capabilities, to avoid any notable database write to happen in an unauthenticated request (which could also lead to race conditions on high traffic sites).
- Subsequently, any new options being requested that were not autoloaded yet would be added also from unauthenticated requests. This would result in minimal write requests over time, but it would be critical since different templates and screens may use different options.
- Avoid autoloading options with values that are greater than a specific threshold (TBD).
- Certain very large options should never be autoloaded since their size would become a problem for alloptions. In this case an additional database query is actually preferable.
- Effectively ignore the
$autoload
parameter ofadd_option()
andupdate_option()
, which for WordPress core eventually would mean these would be deprecated.
By using the autoload
column in the database, the implementation would not require any additional storage than WordPress core is already using today, the only exception being a single new option to store the timestamp of when the “autoload cleanup routine” was last started (which is needed to control when it should restart again from scratch).
In addition, since the module would alter the autoload
column values in the database, it should come with a backup mechanism that could restore the original autoload
column values later if needed.
Something that this proposal does not explicitly include, but could also be thought about further after establishing a first version of the module, would be to also disallow options that are very frequently written to from being autoloaded.
This module would not do the following things:
- Delete any options - it would only ever set the
autoload
value to “no” if an option is no longer important, but deletion should never automatically happen. - Have different alloptions values for different contexts (e.g. as proposed in Module proposal: Cache
alloptions
to load only needed values #347). - Highlight issues with autoloaded options in Site Health (as in the existing experimental module).
If this module is approved and can eventually land in core, it would likely make #347 and the current autoloaded options Site Health check unnecessary, fixing the problem in a central place.
Rationale
A bloated list of autoloaded options becomes a severe performance problem for many WordPress sites over time, unless their databases are regularly inspected either manually or using e.g. a cleanup plugin, thus slowing down the alloptions query or even breaking the caching of it entirely, making that slow query impacting performance even more negatively.
Other
We did an additional brief test, to see how many autoloaded options were actually used with vanilla WordPress core.
- With Twenty Twenty-One, out of 120 autoloaded options, only 67 were actually being used.
- For Twenty Twenty-Two, it was 58 out of 90 options.
- With JetPack, Yoast SEO, and WooCommerce, it already became 121 out of 176 options.
Those are of course very basic situations, but it shows that already for even core with a default theme the module already improves the situation. Likely the performance win is minimal for such a small list, but real world WordPress sites have a much larger list of autoloaded options.
Proof of concept
@markjaquith wrote a proof of concept plugin (very rough, emits UI in the theme footer) just to see if this was feasible:
https://gist.github.com/markjaquith/f21566334133d2843598c064e76f1142