As we presented previously Magento is the best open-source online shopping platform available on the market. So, what is the reason a big number of retailers still prefer hosted platforms or simpler solutions? To answer that I need to provide some details on the technical background of the platform.
Magento is build using Zend Framework 1, which is a very heavy weight framework and although it provides a huge number of features compared to other frameworks (like CakePHP, Symphony, Laravel etc.) the required load time for the factory autoloader takes a lot of time so decreases the response time of your website. The reason for this is that we need to load around 9000 files on a full auto-load. Zend Framework 2 has changed this.
Magento uses the EAV data model for most of it's entities (products, categories, customers, customer addresses) which is scalable at an incredible rate, but unfortunately it slows down performance as sometimes it needs to "walk" through a huge number of tables to get to the required information.
So, as you have figured out the problem is the website performance which affects directly the loading times. By default without any kind of optimization Magento will get an extremely low grade for the First Byte test and will start off with approximately 5s load time for any normal website.
So what can we do to reach a good loading time and not lose the complete features Magento offers and that is OPTIMIZATION.
The Magento optimization process should start with the features Magento offers:
- activate caching from the Magento administration area
- activate Zend Full Page Caching from the administration area under System
- make sure your catalog is properly indexed and you use flat data for your catalog (be careful when you are using attribute related customization which modified content dynamically on the categories or the product detail pages if you do so)
The next choice is what type of webserver you should use. Any Sys-Admin will recommend Nginx. Well, I don't. The reason for this is that setting up nginx in a dynamic production environment is a pain and it creates issues with both routing and modules that expect specific Apache related settings. A better choice is actually LiteSpeed which is completely Apache Compatible or simple Apache, but with the following optimizations up:
- use either workers or process forks and set up apache to generate the required processes based on your hardware (number of cores, RAM, network stability and accepted connections)
<IfModule prefork.c> StartServers 32 MinSpareServers 500 MaxSpareServers 1000 ServerLimit 4000 MaxClients 4000 MaxRequestsPerChild 2000 </IfModule> <IfModule worker.c> StartServers 32 MaxClients 4000 MinSpareThreads 640 MaxSpareThreads 1200 ThreadsPerChild 100 MaxRequestsPerChild 10 </IfModule>
- make sure KeepAlive is enabled and it is configured to use proper timeout and a big number of keep alive requests using the MaxKeepAliveRequests directive
- remove any unnecessary modules by commenting the LoadModule directives or by compiling Apache without unneeded extensions
- use mod-deflate and mod-expiry for caching and gzip compression.
- set the appropriate cache headers
For the database I recommend going further with Perconna. It is Mysql compatible and solves a lot of the issues concerning data access speed (including NOSQL engines access) and loading big queries. It is cloud optimized and it avoids sharding, thus returning accurate data. You can read more at http://www.percona.com/software/percona-server
If Perconna is not for you, go with either an optimized Mysql server or with MariaDB which is actually Mysql, but not hold under Oracle. (Don't say to anyone else that I've told you so). Up until 5.6 MariaDB and Mysql were fully compatible, further there are differences and considering Magento is highly extendable I can't guarantee you will not encounter any issues with newer versions (at least at a community or custom developed module level).
With Mysql there are some clear techniques that need to be used:
- enable query caching
- enable innodb buffering
- increase temporary tables sizes
- increase buffer pool sizes
- increase innodb thread concurrency
Here is a quick snnipet of my.cnf:
symbolic-links=0 query_cache_type = 1 query_cache_size = 64M thread_cache_size = 16 key_buffer = 128M sort_buffer_size = 2M table_cache = 1024 innodb_buffer_pool_size = 20M innodb_thread_concurrency = 16 innodb_flush_log_at_trx_commit = 0 innodb_additional_mem_pool_size = 4M innodb_log_file_size = 5M max_connections = 250 innodb_log_buffer_size = 4M join_buffer_size = 96M tmp_table_size = 96M max_heap_table_size = 96M max_allowed_packet = 32M read_buffer_size = 96M innodb_flush_method=O_DIRECT
There are a lot of other optimizations which you can do, like the usage of Memcached and Varnish HTTP Accelerator,or frontend related optimization like improved image compression, but those in themselves deserve an article, so stay tuned.