Optimising Magento for Performance
Following our earlier entry about installing Magento Enterprise, we thought it would be appropriate to follow up with some tips for getting more from your Magento installation. One of the major criticisms leveled at Magento is its speed; many complain that it is far too slow. In this article we'll go through some steps you can perform to fine-tune your server to allow Magento to run more smoothly and more quickly in a production environment. Our examples are geared at a Debian-based LAMP stack, but most can be adapted for other platforms. Check out our tips on:
- Apache KeepAlive
- Alternative session storage
- and a bonus security tip!
Memcached is a distributed memory caching system that stores data retrieved from the database (or other data source) in memory, allowing repeat reads to retrieve the data from memory rather than needing to query the database again, greatly increasing the speed of web applications.
The first thing to do is install the memcache daemon and client libraries:
root# apt-get update root# apt-get install memcached php5-memcache
To check if memcache is running, you can use the following command:
root# ps -ef | grep memcached
You should ensure that the localhost has been added to the configuration, this can be done using grep as shown here:
root# grep 127.0.0.1 /etc/memcached.conf
This should output -l 127.0.0.1 if localhost is included in the configuration. If not, add this line to the configuration and restart memcached:
root# echo '-l 127.0.0.1' >> /etc/memcached.conf root# /etc/init.d/memcached restart root# /etc/init.d/apache2 restart
You need to create a PHP configuration file to include the module, which on a Debian-based system should be in /etc/php5/conf.d/memcache.ini:
Magento itself can also be configured to utilise some memcache optimisations built into the software. The following XML should be added to the /var/www/app/etc/local.xml file once it has been generated:
<config> <global> ... <cache> <backend><![CDATA[memcached]]></backend><!-- apc / memcached / xcache / empty=file --> <slow_backend><![CDATA[database]]></slow_backend> <memcached><!-- memcached cache backend related config --> <servers><!-- any number of server nodes can be included --> <server> <host><![CDATA[127.0.0.1]]></host> <port><![CDATA]></port> <persistent><![CDATA]></persistent> <weight><![CDATA]></weight> <timeout><![CDATA]></timeout> <retry_interval><![CDATA]></retry_interval> <status><![CDATA]></status> </server> </servers> <compression><![CDATA]></compression> <cache_dir><![CDATA]></cache_dir> <hashed_directory_level><![CDATA]></hashed_directory_level> <hashed_directory_umask><![CDATA]></hashed_directory_umask> <file_name_prefix><![CDATA]></file_name_prefix> </memcached> </cache> </global> ... </config>
The Apache mod_cache module allows Apache to cache content on disk or in memory, thus decreasing page load times. Caching for dynamic sites such as ecommerce needs to be approached with some caution; the cache may become invalid and thus customers may receive stale content. To enable mod_cache perform the following steps:
root# a2enmod cache root# a2enmod disk_cache root# a2enmod mem_cache
Enable disk caching in the disk_cache.conf configuration file by uncommenting the CacheEnable line in /etc/apache2/mods-available/disk_cache.conf. Make sure you remember to restart apache after doing this.
There is also a utility you can install which will clear the disk cache, the following code sample shows how to install and run it:
root# apt-get install apache2-utils root# htcacheclean -d30 -n -t -p /var/cache/apache2/mod_disk_cache -l 100M -i
This will clean our cache directory every 30 minutes and make sure that it will not get bigger than 100MB. You can tune these settings to fit your particular site needs.
Well-written browser software will keep a cache of the webpages a user visits. Each webpage should have a content expiry header directive that tells the browser when the cache expires. If this header is not correctly set then the browser will re-request the content from source with every page hit. In order to ensure that the Magento pages have the correct content expiry in the header, you can add the following block to Magento's .htaccess file:
ExpiresActive On ExpiresDefault "access plus 1 month"
The Apache KeepAlive functionality allows the TCP connection between a client and the server to remain open, allowing multiple requests to be served over the same connection. This can decrease page load times particularly on webpages with lots of images since it removes the overhead of having multiple connections opened. To use this functionality, edit the /etc/apache2/apache2.conf, find the KeepAlive entries, and make sure they are enabled as follows:
KeepAlive On KeepAliveTimeout 2
This will enable the KeepAlive feature; the timeout parameter is in units of seconds.
PHP APC is an Alternative PHP Cache that caches the byte-compiled PHP code, which means that repeat requests to the same PHP script should not need to be recompiled before being served, which will increase performance. This is a pear module, but also has some system dependencies, so to install it we run the following:
root# apt-get install apache2-threaded-dev php5-dev php-pear make gpp root# pecl install apc
The APC configuration file should be created, and on the debian system the path would be /etc/php5/conf.d/apc.ini. We place the following lines into this file:
extension=apc.so apc.shm_size=256 apc.num_files_hint=10000 apc.user_entries_hint=10000 apc.max_file_size=5M
Also make sure that Magento is using APC for caching by editing /var/www/app/etc/local.xml and add the following somewhere inside the <global> tags:
<global> ... <cache> <backend>apc</backend> <prefix>alphanumeric_</prefix> </cache> ... </global>
To verify if APC is installed, we can check if the output of phpinfo includes reference to it, by running the following command from the CLI:
root# php -r 'phpinfo();' | grep 'apc'
Database Session Storage
Typically, database servers are less utilised than web servers. Performance can usually be improved by moving session handling from the web server filesystem into the database server. Magento asks you whether you prefer a file or database session save type, but this is very easy to change in the XML. Open up /var/www/app/etc/local.xml, locate the <session_save> tags, and change the value so it looks like this (the default is <![CDATA[files]]>):
Another alternative is to use memcache for storing the sessions – this isn’t as persistent as the database store, but may be faster:
You can add details of your memcache server in the session save path:
Web pages can be compressed using GZip between the server and the client, reducing the amount of data that needs to be transferred. Although the act of compressing and decompressing adds a performance overhead there is usually a net gain in reducing the amount of traffic especially for large pages. To use GZip compression, enable the mod_deflate module in Apache, and add the following to the vhost for the site:
SetOutputFilter DEFLATE # Netscape 4.x has some problems... BrowserMatch ^Mozilla/4 gzip-only-text/html # Netscape 4.06-4.08 have some more problems BrowserMatch ^Mozilla/4.0 no-gzip # MSIE masquerades as Netscape, but it is fine BrowserMatch bMSIE !no-gzip !gzip-only-text/html # Don't compress images SetEnvIfNoCase Request_URI .(?:gif|jpe?g|png)$ no-gzip dont-vary # Make sure proxies don't deliver the wrong content Header append Vary User-Agent env=!dont-vary
A final tool to consider for performance improvement is MySQLTuner. MySQLTuner is a Perl script which analyses your database and gives recommendations which variables you should adjust in my.cnf to increase performance. This can really help to get the database, often a performance bottleneck for these types of applications, performing as well as possible without needing expensive hardware upgrades. To install and run this utility, simply do:
bash$ wget http://mysqltuner.com/mysqltuner.pl bash$ perl mysqltuner.pl
You see some recommendations for which variables could be changed to improve performance, it is best to make changes incrementally and one at a time so you can see how they affect the performance of the database.
Bonus Security Tip: Changing the Admin URL
Although not an actual performance issue, you can improve security by changing the default URL from ‘admin’ to something more obscure, such as ‘5i8FNvHg’. This will decrease the probability that a malicious user will hit upon your admin log-in page by guessing that the admin site is located at yourdomain.com/admin/, or that automated scripts scanning for Magento admin pages will find it.
To change the admin address you first need to stop Apache and clear the cache:
root# /etc/init.d/apache2 stop root# rm -rf /var/www/var/cache/* root# rm -rf /var/www/var/session/*
Then open up the /var/www/app/etc/local.xml file, locate the <frontName> tag, and change the ‘admin’ part it to something a lot more random, eg:
Then set Apache running again (bearing in mind your site will be down for the duration of this operation!):
root# /etc/init.d/apache2 start
This was a selection of the tips we use to keep our Magento sites running smoothly; but is there anything we missed? If you have comments or tips for other users, please leave us a comment and let us know!