Summary
Optml_Settings::get_site_settings() is called once per image URL during output buffer processing, but it rebuilds its return array from scratch every time by calling $this->get() 39 times. Since the settings never change during a request, this results in massive redundant work on image-heavy pages.
Impact
On a WooCommerce variable product page with ~2,500 image URLs in the output buffer:
get_site_settings() called 2,500 times
- Each call invokes
get() 39 times + sub-methods (get_watermark 6×, get_quality 4×)
- Total: ~136,000 calls to
get() and is_allowed() per page
- ~690ms wall time consumed by Optimole settings lookups alone
Profiled with PHP SPX on a real WooCommerce store (155 products, Woodmart theme, 46 <img> tags expanding to 2,500+ URLs via srcset/JSON-LD/variation data).
Root Cause
The call chain is:
wp_ob_end_flush_all (output buffer flush)
→ Optml_Manager::replace_content
→ Optml_Manager::do_url_replacement
→ Optml_Url_Replacer::build_url (×2,500)
→ normalize_image
→ apply_watermark
→ $this->settings->get_site_settings() ← rebuilds array every time
→ $this->get() × 39
→ get_watermark() → get() × 6
→ get_quality() → get() × 4
get_site_settings() in inc/settings.php has no caching:
public function get_site_settings() {
$service_data = $this->get( 'service_data' );
// ... builds array with 39+ $this->get() calls ...
return [ /* 39 keys */ ];
}
Suggested Fix
Add static caching to get_site_settings():
public function get_site_settings() {
static $cached = null;
if ( $cached !== null ) {
return $cached;
}
$service_data = $this->get( 'service_data' );
// ... existing code ...
$cached = $result;
return $result;
}
This reduces get() calls from ~136K to ~39 (a single invocation) and eliminates ~690ms on image-heavy pages.
Verification
Tested with a mu-plugin that subclasses Optml_Settings and caches get_site_settings():
| Metric |
Before |
After |
Change |
get() calls |
136,244 |
14,050 |
-90% |
get_site_settings() time |
91ms |
1.1ms |
-99% |
| Total wall time |
3,944ms |
3,339ms |
-605ms |
| Function calls |
1,782,978 |
1,534,631 |
-248K |
No functional changes — all settings are read-only during a request.
Environment
- Optimole 4.0.3 (also confirmed unfixed in 4.2.1 on GitHub master)
- WordPress 6.8.3
- WooCommerce 10.4.4
- PHP 8.2
Summary
Optml_Settings::get_site_settings()is called once per image URL during output buffer processing, but it rebuilds its return array from scratch every time by calling$this->get()39 times. Since the settings never change during a request, this results in massive redundant work on image-heavy pages.Impact
On a WooCommerce variable product page with ~2,500 image URLs in the output buffer:
get_site_settings()called 2,500 timesget()39 times + sub-methods (get_watermark6×,get_quality4×)get()andis_allowed()per pageProfiled with PHP SPX on a real WooCommerce store (155 products, Woodmart theme, 46
<img>tags expanding to 2,500+ URLs via srcset/JSON-LD/variation data).Root Cause
The call chain is:
get_site_settings()ininc/settings.phphas no caching:Suggested Fix
Add static caching to
get_site_settings():This reduces
get()calls from ~136K to ~39 (a single invocation) and eliminates ~690ms on image-heavy pages.Verification
Tested with a mu-plugin that subclasses
Optml_Settingsand cachesget_site_settings():get()callsget_site_settings()timeNo functional changes — all settings are read-only during a request.
Environment