making bbPress (and WordPress) work better!

WP performance

How to build HHVM 3.22 master trunk on CentOS 7

HHVM 3.20, 3.21 and 3.22 are still faster than PHP 7.2 especially with many connections under load, however as of October 2017 there still are no official pre-compiled HHVM packages for CentOS 7.x so we need to revisit how to build it by hand, which is not too difficult, just takes most servers awhile to assemble

There are instructions on the HHVM wiki for CentOS7 but they are a year out of date now.

The process is straightforward, first we need to not only make sure we have all the libraries we need but also the development libraries and most recently a newer version of the GCC compiler, we will use GCC 6.3 found in the official SCL Devtoolset-6 for CentOS 7 (trusted because it is built by Redhat/CentOS)


PHP 7.0 Final will ship November 12th 2015

Very exciting to see the PHP team set the date for the PHP 7.0 final (gold) release.

Thursday November 12th – 90 days from today, mark your calendars!

It will be as if millions of servers cried out as their loads were cut in half.

The first PHP 7.0 release candidate will ship August 20th, 2015 (this coming Thursday!)

All changes to PHP 7.0 now are stabilization/fixes only (feature frozen).

In 30 days, on September 14th 2015, the PHP team will start the PHP 7.1 master trunk branch as PHP 5.4 is marked “end of life”

If you need legacy code support, be sure to read my post on how to put mysql functions back into PHP 7.0

WordPress 4.3 benchmark: HHVM 3.9 vs PHP 7.0

A casual Sunday morning benchmark for August 9th 2015 using latest builds:

1000 Front Pages of WordPress (virtually stock default install)
HHVM 11.99, 11.83, 11.81, 11.78, 11.85 seconds
PHP7 11.18, 10.95, 10.85, 10.96, 10.88 seconds

WordPress trunk 4.3 RC2
HHVM trunk 3.9-dev
PHP trunk 7.0 RC1
(on CentOS 7)

How to build HHVM 3.8 on CentOS 7

2015 UPDATE: new wiki page for HHVM on CentOS7 with alternate instructions
While building HHVM (HipHop Virtual Machine) for faster PHP on CentOS 6.x was pretty much a nightmare because almost none of third-party libraries are available from major repositories, the freshly released CentOS 7.0 solves most of this problem as it has far newer packages available from EPEL (because it has roots in more modern Fedora 19).

Note that unlike PHP/PHPNG, HHVM requires major resources to build. You may be used to making PHP in 15 minutes on a little old 256mb 1ghz box. You can forget that with HHVM which is a beast to compile. 1gb ram minimum and lots of cpu power required to keep it an hour or two (this is part of why PHP NG instead is so exciting because it will be so much easier to custom build).

PHP NG within 10-25% of HHVM performance

Zeev Suraski (CTO of Zend and therefore an extremely qualified authority on PHP NG) has written a fascinating article comparing the performance of PHPNG against the current HHVM versions. A must read.


Perhaps even more importantly, he has written about the current state and future of PHP NG.

PHP NG now nearly TWICE as fast as PHP 5.6

correction: php core developers have urged that it is improper to call this version “5.7” (despite the versioning file stating so)

PHP 5.7 PHP NG is still in alpha development, however it is starting to show breathtaking performance improvements over 5.6 while maintaining virtually complete compatibility.

Dmitry Stogov has been hard at work since his first announcement in mid-January 2014 and milestone update in early-May to keep folding in more and more ideas to increase PHP speed (with significant contributions by Xinchen Hui, Nikita Popov and others).

Six months later in mid-July, their efforts are really bearing fruit and PHP 5.7 NG is about to become nearly 100% faster than PHP 5.6 when rendering the front page of a stock WordPress 3.6 installation:

PHP 5.6, 1000 renderings of WP front page = 26.756 seconds

PHP NG,  1000 renderings of WP front page = 14.810 seconds

and he is not even done yet, based on all his proposals and notes as you can follow on


CentOS 7 to arrive in July with performance boost

Red Hat released RHEL 7 on June 10th which means the CentOS 7 community got to work, to prep their release based on the source. It is currently in “QA” release for review and will go to “GA” release (general availability) sometime in July.

The big news, at least for me, is performance improvements over CentOS 6.5
Red Hat claims 11% to 25% speed increase depending on workload:

Is that plausible from just an OS upgrade? Possibly, depending on better use of hardware and how much contention is going on. CentOS 7 will finally bring the linux 3.10 kernel to replace the 2.6.32 kernel in CentOS 6.5 – this means the elimination of the “big kernel lock” and better memory management.

7 will also bring the XFS filesystem as a default, alternative to EXT4. I am not sold on this change. I have seen a number of benchmarks that show EXT4 is faster in many cases, by a significant percent, over XFS (you can still use EXT4 of course). Apparently GRUB was also replaced with GRUB2 which is something I have to research and learn since it is critical for boot.

Want to read about all the new stuff for yourself?
Try the Red Hat release notes or save it for later in PDF format.

Initially there is no direct upgrade path for CentOS 6.5 to 7.
But they are discussing it and promise to explore after the GA release.

PHP 5.4, 5.6, 5.7 WordPress 3.9 Benchmark

update: now with PHP 5.7 (PHPng) comparison

Was really curious to follow up on PHP 5.6 with “real world” benchmarks so I built up a machine today for some quick’n’dirty tests. (I’ll add more tests to this at a later date as I have actual things to do this weekend and this was quite a bit of work).

Everything was allowed to pre-cache heavily, linux, mysql, php opcache, etc. this is just a raw php performance test (but no wp-cache, all dynamic pages)

Two tests: (for now)

1) directly calling the wordpress front page via php-fpm via the fcgi utility, which bypasses all of the web front end (nginx) so it is pure PHP speed

1000 passes (one pass at a time, single file asap via fcgi)
PHP 5.4 median = 28.562 seconds
PHP 5.6 median = 26.783 seconds
PHP 5.7 median = 19.405 seconds

 6.22% improvement with PHP 5.6

32.06% improvement with PHP 5.7

2) full web interface benchmark with logged in admin user, going into view “all posts” in the wp-admin backend (/wp-admin/edit.php) – this makes WordPress work really hard because it is loading all of the engine, plus the wp-admin code, plus authorizing the user via the cookie

1000 passes (one pass at a time, single file asap via curl)
PHP 5.4 median = 42.523
PHP 5.6 median = 39.455
PHP 5.7 median = 29.498

 7.21% improvement with PHP 5.6

30.63% improvement with PHP 5.7

Intel Quad Core i5 @ 3ghz
CentOS 6.5 64bit, MariaDB 10.0.11, Nginx 1.6.0, PHP 5.4.30/5.6.0beta4, Zend Opcache 7.0.4
WordPress 3.9.1 (stock with wp-cron disabled)

All built with GCC 4.8.2 and I made PHP 5.4 and 5.6 both use the same new Zend Opcache (because it is amazing)

I’ll do more comparisons and maybe even build PHP 5.5 at a later date.

Let me know if there are any specific requests for good things to compare.

Added PHP 5.7 (aka PHPNG) something to look foward to in 2015

PHP 5.6 enters final beta,  up to 10% faster than 5.4, 5.5

PHP 5.6 is about to enter its final beta this week or early next.

It is now in “feature freeze” where only bug fixes will be applied to the code.

While PHP 5.5 was actually SLOWER than PHP 5.4 in some cases, it appears they have finally moved performance ahead with PHP 5.6 and informal benchmarks show it to be up to 10% faster than PHP 5.4 (and 5.5) using real-world code.

There will also be some further memory savings with how it handles strings and other data. Given the sheer size and bloat of modern WordPress, it will need every bit of help that PHP can throw at it, so I expect quick adoption on large websites.

Fortunately there are very few backward incompatible changes with PHP 5.6

The biggest “problem” will be deprecated warnings for users adapting to it from previous versions – but those warnings can be masked for now to reduce noise in error logs.

For example here is how I handle such noise on production servers via php.ini:

error_reporting = E_ALL & ~E_STRICT & ~E_DEPRECATED & ~E_NOTICE

The future of PHP looks quite exciting now with the recent proof-of-concept demonstrated via PHPNG (PHP next generation), where it might become 50% faster in some cases based on internal restructuring, memory handling modeled on jemalloc and just-in-time compiling. WordPress was already demonstrated to be 20% faster in an early experiment over PHP 5.5

WordPress 10% faster with Zend Optimizer Plus vs APC opcode cache

As PHP internals explores replacing the APC opcode cache with an open-sourced Zend Optimizer Plus an interesting benchmark was published. It shows WordPress serving nearly 10% more pages per second than APC while using Optimizer+ (both under PHP 5.5).

apc-vs-optimizerplus has 2200 servers

500 of them are just for MySQL with 500 million tables. More here:

An Easy Way to Speed Up MySQL FullText Natural Search on Large Tables

As your WordPress or bbPress install grows over the years, if you have a large site you will notice the search slows down quite a bit on large tables. Another problem is the quality of search results becomes poor as it has to muck through more and more posts.

It’s difficult to jump to a solution like sphinx right away, and things like the google api are not aware enough about the context of your content, so some people will code their own searches within MySQL in the meanwhile.

For example, a minimal search is done something like the following, taking advantage of MySQL’s natural search mode which takes into account the number of times the words appears and their proximity to return a score.

SELECT post_id,  MATCH (post_text) AGAINST ('some words') AS score
FROM posts WHERE MATCH (post_text) AGAINST ('some words')

In my situation, using a much more complex version of that query that takes into account all posts in a topic was taking up to 12 seconds which was completely unacceptable.

So it occurred to me that MySQL also has a binary search mode that is far faster. It’s not what I wanted for the overall results because it’s relevancy can be poor, but it instead could just be used to eliminate posts that would have to be scanned. Anytime you can eliminate rows in mysql you will get a speed boost.

So simply do this instead:

SELECT post_id,  MATCH (post_text) AGAINST ('some words') AS score
FROM posts WHERE MATCH (post_text) AGAINST ('some words' IN BOOLEAN MODE)

Basically that IN BOOLEAN MODE will eliminate rows very quickly that do not have either of those words in them, but the SELECT still calculates a valuable natural search score for the remaining results.

When using boolean mode you have to take some extra steps to sanitize the query because some characters have special meaning so keep that in mind but it’s trivial to do.

Eventually I took it a step further and preprocessed the search terms even further. (more…)

Fix large image attachments in WordPress

An annoying problem we have encountered with WordPress is that if an attached image is under the alloted dimensions for the post, WordPress will not attempt to further manipulate it or resave it.

This typically happens when non-tech authors upload photos from photoshop saved at the highest quality settings, but already sized down to the post width.

Only the smaller dimensions will be created, sometime leaving main images with extremely large file sizes in posts which are a big problem, especially for mobile visitors. But you really do not want megabytes of images on each page, for any kind of visitor.

So here is a filter I whipped up to catch that problem and resave the jpegs at 90% quality, progressive format, which will typically cut the size down to one-third (100k) or less with no perceptible loss of quality. It has the added bonus of stripping exif data and other meta (like hidden adobe fingerprints) from the images to reduce the size as much as possible for the most speed.

function fix_large_jpg($metadata) {
	if (!empty($metadata['width']) && $metadata['width']<601) {
		$file=wp_upload_dir(); $file=$file['basedir'].'/'.$metadata['file']; 
		if (file_exists($file) && filesize($file)>200000) {
			$imageinfo = getimagesize($file);
			if (!empty($imageinfo['mime']) && $imageinfo['mime']=='image/jpeg') {
				if ($new) {
	return $metadata;

This could be expanded for png but jpeg was really the main problem and easily solvable by forced resaving. Note that the re-save comes AFTER the lower sizes are created, allowing them to use the high quality source before it’s replaced.

The only hardcoded settings are the 600 pixel width which you can edit to what is used for the posts on your site, and the 200k filesize trigger which you can lower or increase as desired.

WordPress nearly 10% faster on PHP 5.4 than 5.3

The speed improvements in PHP 5.3 over PHP 4 were significant.

Now comes news of some additional improvements to squeeze out nearly 10% more performance:

WordPress desperately needs every ounce of help it can get as it grows more and more sluggish with every release, so this is helpful news.

Even faster APC PHP cache by turning off file stat

I’ve recently had to abandon using eaccelerator because they are just not keeping up anymore with PHP releases and they even removed variable data cache support just to get PHP 5.3 compatibility. It’s sad because they were the fastest and most stable for years.

So I have been testing xcache and APC instead.

One trick I use on large/active servers for an additional performance boost is to turn off the file stat feature on the PHP opcode cache. This makes it stop checking the timestamp on each and every PHP file executed. WordPress for example has over 100 php files totaling nearly 3 megabytes on a typical install.

You’d use ONE of these directives in php.ini depending which opcode cache you use:

(whatever happened to) MySQLTuner 2.0

MySQL DBAs are amazingly smart, they really impress me.

It’s really hard to figure out the right way to make MySQL perform better. Webservers and PHP have been improved to the point where mysql is often becoming the bottleneck.

I just finished porting over MySQL-Report into bbPress as a plugin. It was originally written by Daniel Nichter in Perl and then Munroe Richard converted it to PHP for Drupal, so I “borrowed” a great deal of his code to save some time. I am not that thrilled with the original code quality but I am feeling too lazy right now to rewrite it, and it works well enough.

Other analysis tools I use are tuner-primer and MySQLTuner (v1.2) The mysql summary from aspersa (now in the Percona Toolkit) is also somewhat helpful but not as useful.

For realtime tracking the updated version of MyTop from Mark Grennan (originally by Jeremy Zawodny) is somewhat useful on busy servers.

Now, does anyone know whatever happened to MySQLTuner 2.0 ?
Seems like they stopped working on it in 2010

Nice slideshow on it from Sheeri Cabral

Video presentation with that slideshow

Another Performance Regression in WordPress 3 Future

MySQL 5 is proven to be slower than MySQL 4, and WordPress doesn’t require any MySQL 5 specific features to operate.

But they announced today that WordPress 3.2 will require MySQL 5.0.15

MySQL 5 has performance improvments mostly for InnoDB which WordPress does not use. MySQL 4 is faster at MyISAM which the is the more common db format (and used by WP).

Also, they are insisting that servers run PHP 5.2 minimum for WP 3.2

While PHP 5.2 is faster than PHP 4.4 (and PHP 5.3 is measurably faster than 5.2) it’s not very hard at all to support PHP 4.4 In fact I’m sure they are going to have to go out of their way to force PHP 5 to be required by actually REMOVING simple code that helps PHP 4.4 already in WP.

So why not keep software flexible when it’s easy? The reality is this is probably to help keep reports of security problems with WordPress down by forcing people to keep their servers up to date.

Personally I don’t think that is WordPress’s business or responsibility but I guess people have a choice which software they want to use, especially when it’s free.

ps. You know what else just dawned on me – Matt has data on a million servers that run WordPress when they “phone home”. This doesn’t bother anyone?

WordPress still uses the nasty SQL_CALC_FOUND_ROWS

(update: please don’t try this patch as is on WP versions newer than 2.8 – I am only leaving it here as a suggestion if some coder in the future decides to tackle the problem)

We’ve known for over two whole years now that SQL_CALC_FOUND_ROWS did nasty things in bbPress 0.8

It was fixed by mdawaffe (Michael) after discovering how SQL_CALC_FOUND_ROWS caused an overload on the Automattic forum servers due to a MySQL bug.

But to this very day, it’s still used in all WordPress versions, up to and including 2.8.2

(Even more ironic, now that bbPress 1.0 has switched to the backPress core which is based on WordPress, SQL_CALC_FOUND_ROWS is back inside bbPress, though it works around the bug)

SQL_CALC_FOUND_ROWS is typically three times slower than using COUNT() on the same query without LIMIT and ORDER restrictions.

I’ve seen at least one slow-log for MySQL that is FULL of SQL_CALC_FOUND_ROWS queries from a large WordPress installation on a dedicated server that took 11-15 seconds per query (and crashed MySQL, repeatedly).

Here is my quick & dirty patch to the WordPress (and BackPress) core that attempts to change SQL_CALC_FOUND_ROWS to the COUNT() workaround – it’s inside wp-includes/query.php – it’s tested working but not heavily tested so use with caution and let me know if you have improvements?

My changes are against the file from WP 2.5.1 but the file has barely changed since 2.5, even 2.8 is virtually the same so it should be easy to modify other versions.

There is one other use of SQL_CALC_FOUND_ROWS left in WordPress but it’s in the admin section so I am not going to worry about it for now.

More about the MySQL bug due to it’s poor optimization: (cache) (cache)

Some Tech Tips to find a better WordPress or bbPress Host

I’m going to reprint some advice here that I shared on as there is a great deal of confusion and misguided ideas over how to find a good host for WordPress or bbPress.

A quick google shows there are dozens of “Top 10” lists of hosts. Some are dubious with commission links and others that as well intentioned as they are, focus on non-technical aspects that don’t matter much in the end.

There is a MASSIVE amount of competition in the hosting world and virtually everyone offers things like “uptime guarantees” and seductive low prices to try to grab customers. In the end it doesn’t matter. You can go with a provider that’s been highly recommended and have the worst experience, or try one out that others have complained about and have a good experience.


PHP 5.3 feature freeze tomorrow? alpha1 July 31st?

I am uncertain if they are still on schedule but if so, this is very exciting because PHP 5.3 will realize significant speed improvements for all PHP programs on the web (15% for WordPress). They are suggesting a “stable release between mid September and mid October”.

PHP 5.3 brings new features (namespaces, late statics binding, and the garbage collector, for instance) but the refactoring of the argument stack, for example, and other optimization patches have lead to a measurable performance improvement (PHP 5.3 is 1.2 times faster than PHP 5.2 for raw execution speed).

Here’s a nice “slideshow” in PDF format of what’s new in PHP 5.3 by Ilia Alshanetsky

WordPress will be 15% faster under PHP 5.3

I may finally upgrade my servers from PHP 4.4.8 to PHP 5.3 when it’s released. I’ve been sticking to PHP 4 because I don’t use anything that needs 5.x and 5.0 is slower than 4.x is some situations.

But apparently the performance has been put back into 5.3 according to this obscure posting on which quotes WordPress (among others) as an example of performance improvements:

Is it bad when you start daydreaming about code?

I had this daydream the other day where I reversed the way WordPress/bbPress works and instead of running forwards by loading the entire engine first, then ALL the plugins and then finally the template, it worked BACKWARDS – where it first loaded the template and analyzed what was being requested, then loaded only the parts of the core it needed and then the plugins that were flagged as affecting the required output.

Way more complex, sure. But way less code execution and less plugin loading – and far, far, far more easy to cache parts of the pages while allowing other parts to be dynamic, without having to load nearly 500k of code among nearly 100 files.

The WordPress/bbPress Performance Limit

I was looking at some of the “most requested features” for WordPress and I noticed that “Make It Faster” was pretty high on the list.

I’ve learned a lot about WordPress code over the past few years but even more so after working with it’s forum spinoff bbPress. A few things about WordPress/bbPress performance became obvious when I starting noticing that another plugin developer’s forum running SMF was running considerably faster than bbPress and WordPress on the same poorly performing host. I took SMF apart to understand why and here’s what I found:

WordPress cannot (in theory) be made much faster, unless entire pages are made static with a caching system and it’s core is not even loaded for the visitor. It’s simply a limit of WordPress’s architecture and would require an entire rewrite to change. If you have mysql caching turned on and an opcode cache (apc, eaccelerator, xcache, etc) that’s the most you can (easily) do before solutions like wp-cache.

The reasons why include:

1. dozens upon dozens of files that have to be included before any page rendering can begin. Other blog/cms software tries to keep this number down but in WordPress it’s almost runaway. Even an opcode cache must check the timestamp on the source files so the filesystem is kept constantly busy – if it’s not in the filecache, there is a performance hit. If it’s being rendered on a different server from where the files are stored (like on Dreamhost and others) there is even more of a performance hit.

2. Each plugin is a separate file that is not a direct mod on the source but an additional include that is required to load and more code to execute. All plugins are loaded regardless of what kind of page is being rendered. See above why this is a problem. Your WordPress setup can easily be requiring near 100 files to load and 500k of code to execute before a single character is output.

3. All output goes through a language translation hook. Even if you are using the default language this will always be slower than direct output.

4. Output is done in bits and pieces with typically no buffering done (ala ob_start) to accelerate and smooth this process. Any programmer should know from experience that outputting a few characters at a time, 1000 times is far slower than storing them all up in a string and dumping the few thousand all together at once at the end.

All these weaknesses can also be found in bbPress (the forum software that is based on WordPress architecture). Maybe oneday a great mind will come up with a magic, backwards compatible speedup solution without rewriting the core but I doubt it will be any time soon.

Despite these weaknesses, on a single dedicated or VPS server with proper resources, proper opcode, mysql and file caching, WordPress (and bbPress) can give just about any other blog/cms software a run for it’s money. The problems begin when these performance solutions are simply not available on a shared hosting server.

ps. I’ll also note that I am not abandoning WordPress or bbPress anytime soon. The benefits of their plugin architecture far outweigh the server performance requirements. Another method for speedup that I did not mention is that replacing apache with lighttpd or litespeed which can also be a big benefit but of course that is much more work than simply turning on the mysql cache and installing an opcode cache.

bbPress Benchmark, performance diagnostics

I’ve made another bbPress plugin, this time to benchmark and diagnose performance problems in page load times – bbPress Benchmark.

It is based on Jerome Lavigne’s Query Diagnostics for WordPress but I have taken it much further in what it measures (plugin & template load times, etc.) Here’s the story of why I created it: (more…)