Lighthouse – WordPress Performance Plugin Review

Like many rants, this one starts with a promise. One made by the developers of Lighthouse on their marketing page:

…optimize MySQL tables by removing all unused table space (both MyISAM and InnoDB)…

Lighthouse WordPress

All unused table space for InnoDB via a PHP plugin? Suspicious, I got my hands on a copy of the plugin to see how it accomplishes this claimed feat. Well, obviously it didn’t reclaim all InnoDB tablespace, just some of it using the OPTIMIZE TABLE method (only effective when innodb_file_per_table is set to “on” which is enabled by default in MySQL 5.6.6 and higher). The ibdata file remained untouched.

Okay, no problem, not unexpected. But then I read into some of the other code and a second, much more substantial promise:

A zero-footprint tuning plugin…

…I became pretty angry. I’ve always been a skeptic of magic optimization plugins, and Lighthouse was unfortunate enough to get my review.

Since the code is licensed under the GPLv3 (“This program is free software: you can redistribute it” — GPLv3) here’s a download (version 1.7.0) for those wishing to follow along on what I think is wrong with all-in-one speedup solutions for WordPress these days.

Lighthouse 1.7.0 has 64 different options. I’ll outline three things that obviously do more harm than good.

autoload

Oh, the evil autoload! Yes, it’s evil in some cases, yet autoloading is there for a good reason – option caching (see wp_load_alloptions). Basically, the core will perform one query to the database to retrieve options that core, plugin and theme developers deem often used.

What does Lighthouse do? It adds 64 of its own options with autoload set to “no” (see function lighthouse_install). And what does this result in?

get_option autoload

…up to 64 additional database queries against the options table on every single page load. So just by installing Lighthouse, without any options enabled whatsoever, our WordPress site is incurring an additional performance hit due to Lighthouse options that are queried one by one on every single page load.

The Lighthouse settings screen displays a nice “Queries Saved” statistic, which obviously doesn’t go down by 64 queries every time the plugin is run. I made a quick change to subtract the amount of non-autoloaded options and got this after 3 minutes of browsing single-handedly.

Lighthouse Queries Saved

Oh and speaking of stats, those are updated on every page load as well. More performance drag.

Bad.

Cache headers

Another option in Lighthouse is designed to optimize page cachability by adding special headers (lhf_http_headers function). Let’s see:

header("Cache-Control: private, s-maxage=120"); is added to all pages. private!? I present to you section 14.9.1 of RFC2616, the HTTP/1.1 protocol “specification”, which clearly states the following: Indicates that all or part of the response message is intended for a single user and MUST NOT be cached by a shared cache..

So effectively, by setting it to private for all pages, the plugin effectively tells caching servers to only allow caching of this page for one specific user. I highly doubt that this was the intention…

And immediately following that, Lighthouse decides to try and generate Etags for the pages. How?

$etagFile = md5_file($_SERVER['SCRIPT_FILENAME']);

WHAT!? $_SERVER['SCRIPT_FILENAME'] is almost always index.php and is always b61b25303be0f573a6b9446d5cbe3a5b for any standard WordPress page going through index.php. This will confuse the heck out of cache implementations relying on Etags. And return a 304 HTTP response for pages that were not really cached because of a complete collision on Etags.

And then something that makes me even more furious:

session_start

The session_start function is public enemy #1 when it comes to page cachability (followed by tracking and ad cookies). Check out this great article on the issue. Similar to the “private” cache control header, it forces caching implementations to store the same page for different users separately, completely defeating the purpose of page caching (in an unauthenticated state, obviously).

Starting a session for anonymous users that are browsing regular pages that are meant to be cached won’t work, unless the caching implementation is configured to ignore session headers (which spells trouble for cases where they’re legitimately used).

Starting a session on high-traffic sites, that are not ready to handle sessions, without preparing beforehand will heavily trash the server resources due to disk-based (default implementation) session flocks. Risky move.

Conclusion

So, in most cases, by merely functioning, Lighthouse takes up more resources than it tries to free and optimize. And impedes cacheability. The lesson?

Never, ever, ever mindlessly slap a plugin on to solve your WordPress performance problems, especially in serious production-grade environments. Never. No caching plugins, no “tuning” plugins, nothing. Not before you intimately know all bottlenecks (by actually profiling your code, rather than paying and praying), why they’re there and what could be done about them. And after you do, you have to intimately know the solution, because in many cases, like adding Memcached as an Object Cache backed, or installing all-in-one performance plugins for WordPress, adverse effects are certain to follow.

</rant>

TL;DR – The Lighthouse WordPress plugin, from what I’ve seen and measured, negatively impacts performance despite its zero-footprint claim and makes some really senseless optimization decisions.

P.S. Did I mention Lighthouse has an option that removes the capital_P_dangit filter? 😀