Created
September 11, 2022 23:08
-
-
Save markjaquith/f21566334133d2843598c064e76f1142 to your computer and use it in GitHub Desktop.
Proof of concept alloptions optimizer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Plugin Name: Alloptions Optimizer | |
* Author: Mark Jaquith | |
*/ | |
class AllOptionsOptimizer { | |
private static $usedOptions = []; | |
private static $allOptions = []; | |
private static $allOptionsBytes; | |
const LAST_RUN_TIMESTAMP = 'alloptions_optimizer_last_run'; | |
const RUN_EVERY = WEEK_IN_SECONDS; | |
public static function init() { | |
$allOptions = wp_load_alloptions(); | |
self::$allOptionsBytes = strlen(implode('', $allOptions)); | |
self::$allOptions = array_keys($allOptions); | |
add_action('all', [self::class, 'monitorOptions']); | |
add_action('wp_footer', [self::class, 'showStats']); | |
if (self::isOptimizing()) { | |
add_action('shutdown', [self::class, 'saveResults']); | |
} | |
} | |
private static function shouldBeOptimized() { | |
if (defined('WP_CLI') && WP_CLI) { | |
return false; | |
} | |
if (defined('DOING_CRON') && DOING_CRON) { | |
return false; | |
} | |
if (defined('DOING_AJAX') && DOING_AJAX) { | |
return false; | |
} | |
if (is_admin()) { | |
return false; | |
} | |
$lastRun = get_transient(self::LAST_RUN_TIMESTAMP) ?: 0; | |
return (time() - $lastRun) > self::RUN_EVERY; | |
} | |
private static function isOptimizing() { | |
return self::userWantsToOptimize() || self::shouldBeOptimized(); | |
} | |
private static function userWantsToOptimize() { | |
return isset($_GET['alloptions']) && $_GET['alloptions']; | |
} | |
private static function usingOption($option) { | |
self::$usedOptions[$option] = true; | |
if (!self::isOptimizing() && !self::isAutoloadedOption($option)) { | |
self::makeOptionsAutoloaded([$option]); | |
} | |
} | |
public static function monitorOptions($filter) { | |
if (strpos($filter, 'option_') !== 0) { | |
return; | |
} | |
$option = substr($filter, 7); | |
if (strpos($option, '_transient_') === 0 || strpos($option, '_site_transient_') === 0) { | |
return; | |
} | |
self::usingOption($option); | |
} | |
private static function isAutoloadedOption($option) { | |
return in_array($option, self::$allOptions, true); | |
} | |
private static function getUnusedOptions() { | |
return array_diff(self::$allOptions, array_keys(self::$usedOptions)); | |
} | |
private static function makeOptionsNotAutoloaded($optionNames) { | |
return self::makeOptionsAutoloaded($optionNames, false); | |
} | |
private static function makeOptionsAutoloaded($optionNames, $autoload = true) { | |
global $wpdb; | |
$autoload = $autoload ? 'yes' : 'no'; | |
$optionNames = array_map(fn ($option) => "\"$option\"", $optionNames); | |
$optionNames = implode(',', $optionNames); | |
$wpdb->query(sprintf("UPDATE $wpdb->options SET autoload = '%s' WHERE option_name IN(%s)", $autoload, $optionNames)); | |
} | |
public function wasUsed($option) { | |
return isset(self::$usedOptions[$option]); | |
} | |
public static function showStats() { | |
echo "<div style='display: flex; align-content: center'><div style='display: inline-block; border: 1px solid black; padding: 10px; margin: 10px auto;'>"; | |
echo "<p id='alloptions' style='text-align: center'>WordPress used " . count(self::$usedOptions) . " of " . count(self::$allOptions) . " autoloaded options.</p>"; | |
echo "<p id='alloptions' style='text-align: center'>autoloaded options are " . round(self::$allOptionsBytes/1024) . " KB</p>"; | |
if (!self::isOptimizing()) { | |
echo "<p style='text-align: center'><a href='/?alloptions=1#alloptions'>Optimize Now</a></p>"; | |
} | |
echo "</div></div>"; | |
if (self::userWantsToOptimize()) { | |
echo "<script>window.location = window.location.href.replace(/alloptions=1/, '');</script>"; | |
} | |
} | |
public static function saveResults() { | |
// Make unused options not be autoloaded. | |
self::makeOptionsNotAutoloaded(self::getUnusedOptions()); | |
// Update the timestamp. | |
set_transient(self::LAST_RUN_TIMESTAMP, time(), time()); | |
} | |
} | |
AllOptionsOptimizer::init(); |
My set_transient
TTL is wrong. Should be self::RUN_EVERY
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
substr
is probably faster. We have to bail ASAP on theall
hook.