When we asked our readers what topic they’d like to cover in our tutorials three stood out the most:
- Site speed optimization
- Security
- WP Admin speed optimization
We’ve covered the former two in our previous tutorials, so today, it’s all about optimizing your belowed wp-admin
.
Due to it’s dynamic nature we can’t do page caching, but that doesn’t mean we can’t make it snappier!
Note: The techniques I’ll show you here speed up your WordPress in general (not just the admin), but if you do any kind of page caching (described in another tutorial) then it won’t have much impact on the visitor-facing side.
Before we get started
In order to follow this tutorial, you’ll need your own virtual private server (see this tutorial if you don’t have one), running Ubuntu 14.04 x64 and Nginx as the web server.
Note that actions we’ll perform here may not only break your WordPress but the server as well, so make sure you have backups – or even better – try it out in a staging/testing environment first.
Y U slow wp-admin?
There are two processes that take place once we load any wp-admin page: PHP processing (compiling PHP code into code that computer can understand) and MySQL queries (database operations). The more plugins you have, the slower your wp-admin gets. Sounds familiar?
Luckily, we can optimize both, PHP processing with HHVM and MySQL with object caching (more on that soon).
Install HHVM
HHVM is a virtual machine, developed by some smart engineers at Facebook that basically replaces PHP-FPM as our PHP processor. Well almost; The problem is that it’s what we called a bleeding edge software, meaning it has not been extensively tested in production environments (outside Facebook, that is), so what we’ll do is use both; HHVM will be our primary PHP processor with PHP-FPM as a fallback.
This way we get all the benefits that HHVM brings to the table and PHP-FPM will take over in case it crashes. Worry not, this all takes place automatically in the background so visitors won’t even notice that something went wrong.
To install HHVM, enter the following commands (as per official documentation):
$ sudo apt-get install software-properties-common
$ sudo apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0x5a16e7281be7a449
$ sudo add-apt-repository 'deb http://dl.hhvm.com/ubuntu trusty main'
$ sudo apt-get update
$ sudo apt-get install hhvm
Now that HHVM is installed, we need to install it as a FastCGI interface, so run:
$ sudo /usr/share/hhvm/install_fastcgi.sh
Now install (or replace) the command line interface (provided by php5-cli) with HHVM:
$ sudo /usr/bin/update-alternatives --install /usr/bin/php php /usr/bin/hhvm 60
And last, make sure HHVM is started automatically, when system boots up:
$ sudo update-rc.d hhvm defaults
To make sure it’s working properly, enter $ php -v
and you should see something like in the following screenshot:
Now that HHVM is working properly, it’s time to configure Nginx to connect to it rather than to PHP-FPM, but we need to make a small correction first (optional, but my personal preference). Edit /etc/hhvm/server.ini
, comment out the line with the port and the following line to it:
hhvm.server.file_socket=/var/run/hhvm/hhvm.sock
The final file should look like this:
Restart HHVM ($ sudo service hhvm restart
) and you should be all set for Nginx configuration.
Open your virtual host file for the WordPress site you’re configuring this (in my case, that’s in /etc/nginx/sites-enabled/www.wp-kickstart.com
):
$ sudo nano /etc/nginx/sites-enabled/www.wp-kickstart.com
In there, locate the location block responsible for PHP processing and replace it with these two:
location ~ .(hh|php)$ {
proxy_intercept_errors on;
error_page 502 = @fpm;
try_files $uri /index.php;
include fastcgi_params;
fastcgi_pass unix:/var/run/hhvm/hhvm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_index index.php;
}
location @fpm {
try_files $uri /index.php;
include fastcgi_params;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_index index.php;
}
Notice the error_page 502
directive? That’s our security net; If, for some reason, HHVM crashes or doesn’t respond to the request, PHP-FPM takes over and processes it as if nothing happened.
Install Monit
This step is optional, but it’ll make sure that HHVM gets restarted properly, whenever it consumes to much memory or processor. And you don’t want to check manually whether HHVM crashed. Because you have other stuff to do.
Monit is a process (running in the background) that’s constantly checking other processes, in more than one way: How much resources they use, are they even running, are the listening to correct addresses/ports, etc. Monit is what you’d call a system guard dog.
Installation is simple, just run the following command:
$ sudo apt-get install monit
This will install and start Monit, but it won’t check any processes out of the box, for that we need to add a configuration file:
$ sudo nano /etc/monit/conf.d/hhvm
add the following contents in:
check process hhvm with pidfile /var/run/hhvm/pid
group hhvm
start program = "/usr/sbin/service hhvm start" with timeout 60 seconds
stop program = "/usr/sbin/service hhvm stop"
if failed unixsocket /var/run/hhvm/hhvm.sock then restart
if mem > 400.0 MB for 1 cycles then restart
if 5 restarts with 5 cycles then timeout
Before we restart Monit, open it’s main configuration file /etc/monit/monitrc
and around line 50, you should see a set mailserver
directive. Uncomment it and enter your mail server info so it looks something like this:
set mailserver smtp.gmail.com port 587
username "your_email@example.com" password "your_password"
using tlsv1
Then scroll down the file, and at line with set alert
(around line 115) add your email to be alerted when anything goes wrong:
set alert your_email@example.com with reminder on 15 cycles
If you want to enable Monit status reporting, you should also locate the set httpd
directive (around line 123) and make sure these lines are uncommented:
set httpd port 2812 and
use address localhost
allow localhost
Save and close the file, then restart Monit in order for the configuration we just did to start working:
$ sudo service monit restart
To check our services’ statuses just run $ sudo monit status
.
That’s it, your loyal guard dog Monit is now monitoring HHVM. If you want to monitor other services I’ve written a gist with common ones configured – just copy them into separate files (in the same directory that we configured HHVM in) and restart Monit.
—
Improve object caching with Redis
With HHVM up and running we improved PHP processing time so now, let’s focus on the second mayor bottleneck: MySQL queries.
WordPress comes with it’s own object caching solution but the problem is that it’s not persisted (saved) across queries, meaning it has to be re-generated on every request. Clearly, that doesn’t help us much in terms of performance, so we need to make it persistent.
One way to do that would be to save it to the database, but that defeats our purpose to make less queries, which is why we will store them in Redis. Redis could be considered a database engine that stores data not on hard drive but in memory (which is orders of magnitude faster to write to and read from compared to the hard drive).
Installing Redis only takes one command:
$ sudo apt-get install redis-server
There is no configuration needed, it works out of the box!
Since PHP doesn’t come with Redis support we also need to install the module for that:
$ sudo apt-get install php5-redis
Now that Redis is running (and PHP knows how to connect to it), it’s time to tell WordPress that it should use it for object caching.
First, you need to open wp-config.php
and let WordPress know what host and port Redis runs on, and add a salt to keys (especially important if you’re running multiple WordPress sites on the same server):
define( 'WP_CACHE_KEY_SALT', 'mydomain_' );
$redis_server = array( 'host' => '127.0.0.1', 'port' => 6379, );
Now we need to install WP Redis plugin. Do not activate it as you’ll most likely see an error; What you should do instead is copy the object-cache.php
file that it comes with, and put it in the wp-content
:
$ cd /path/to/wordpress
$ cp wp-content/plugins/wp-redis/object-cache.php wp-content
That’s it, WordPress will start caching to Redis automatically when it finds the object-cache.php
file in place! To verify it’s working, run $ redis-cli monitor
and refresh the page (while being logged in). What you should see is Redis activity log of keys being set and retreived.
Conclusion
Caching is an important measure that all web applications (and WordPress is no exception) need to leverage in order to provide great user experience – nobody likes to wait for slow responses!
With HHVM and Redis, we’ve taken an important step in making wp-admin fast and enjoyable to use.
Do you have any tricks of your own? Let me know in the comments below.