Close Support
When you purchase a VPS server with 512MB of RAM on board and 1 CPU Core, then using the default settings for such services as MySQL / PHP / Apache is a very bad idea. Currently I have launched 3 sites on the cheapest tariff plan with 512MB RAM / 1 CPU. I’m not completely sure, but attendance is about 5-10 thousand visitors a day. Next, I want to share the instructions on how to optimize LAMP using only 512 MB and without going into swap. Usually, with this setting, 256 – 378Mb of memory is used and everything works pretty quickly.
Before optimizing, let’s take a look at the amount of memory used. To do this, execute the following command:
$ free -m
In order to see the list of running processes and sort them by memory usage, you need to execute this command:
$ ps -eo pmem,pcpu,rss,vsize,args | sort -k 1 -r | less
We configure the LAMP server to consume a small amount of RAM. Stop, turn off unnecessary services.
The first and obvious question to ask is “what services do I not need to use?”. Recently, I found a very handy utility for managing services. It is called “sysv-rc-conf” and manages services using pseudo-graphics and checkboxes. Looks like this:
Do not start the X server, turn off all unnecessary services and configure Apache, MySQL, PHP only with the basic necessary functionality.
The biggest problem with Apache is the amount of RAM it uses. I will consider the following ways to speed up the work and reduce the consumption of RAM:
Prefork — here Apache generates many processes. By default, a large number of allocated, which leads to the consumption of server memory. Make sure that apache2.conf is not configured to run too many servers or has a lot of spare. Below is an example:
StartServers 1
MinSpareServers 1
MaxSpareServers 3
MaxClients 10
MaxRequestsPerChild 3000
StartServers 1
MinSpareThreads 5
MaxSpareThreads 15
ThreadLimit 25
ThreadsPerChild 5
MaxClients 25
MaxRequestsPerChild 200
Also, be sure to adjust the “KeepAliveTimeout” setting to 10 or 15. In my opinion, 15 seconds is too much, than a small page is required for viewing and shorter than required for a long pageview.
The comfigured by default Apache Web server loads too many unnecessary modules. Check which modules are installed and enabled by the following command:
# apache2ctl -M
Below is a list of modules that are required for WordPress:
LoadModule dir_module modules/mod_dir.so
LoadModule log_config_module modules/mod_log_config.so
LoadModule mime_module modules/mod_mime.so
LoadModule setenvif_module modules/mod_setenvif.so
LoadModule alias_module modules/mod_alias.so
LoadModule authz_host_module modules/mod_authz_host.so
LoadModule rewrite_module modules/mod_rewrite.so
You need to comment out the other modules to save memory. Or you can enable / disable modules through the command line. To enable, use the command:
# a2enmod module_name
To disable:
# a2dismod module_name
After the done manipulations, you must necessarily restart the Apache web server:
# service apache2 restart
If you want to achieve maximum performance, you definitely need to limit the logging. On my server, I set the level of “error” (errors). Also, if you do not need detailed statistics, you can disable the User-Agent or the http-referer logging.
# ErrorLog: The location of the error log file.
# If you do not specify an ErrorLog directive within a
# container, error messages relating to that virtual host will be
# logged here. If you *do* define an error logfile for a
# container, that host's errors will be logged there and not here.
#
ErrorLog ${APACHE_LOG_DIR}/error.log
#
# LogLevel: Control the number of messages logged to the error_log.
# Possible values include: debug, info, notice, warn, error, crit,
# alert, emerg.
#
LogLevel error
Fine tuning MySQL to use a small amount of RAM is quite simple.
Next we will consider the following types of MySQL settings:
To optimize MySQL, we need to edit the file/etc/mysql/my.cnf.
Mysql provides several table storage engines. The two most popular are InnoDB and MyISAM. The main differences between them:
The problems with table-level locking are noticeable only on very busy servers. For regular websites, MyISAM shows better performance on cheap servers.
If you decide to use the MyISAM table, you need to add the following lines to the my.cnf configuration file:
default-storage-engine=MyISAM
default-tmp-storage-engine=MyISAM
If you have only MyISAM tables, you can disable the InnoDB engine, thereby saving RAM by adding only one line to my.cnf:
skip-innodb
If you have used InnoDB in the past, then below I give you a script that automatically converts all InnoDB tables to MyISAM.
#!/bin/bash
MYSQLCMD=mysql
for db in `echo show databases | $MYSQLCMD | grep -v Database`; do
for table in `echo show tables | $MYSQLCMD $db | grep -v Tables_in_`; do
TABLE_TYPE=`echo show create table $table | $MYSQLCMD $db | sed -e's/.*ENGINE=\([[:alnum:]\]\+\)[[:space:]].*/\1/'|grep -v 'Create Table'`
if [ $TABLE_TYPE = "InnoDB" ] ; then
mysqldump $db $table > $db.$table.sql
echo "ALTER TABLE $table ENGINE = MyISAM" | $MYSQLCMD $db
fi
done
done
Below are a few parameters that can be adjusted to speed up the MySQL server.
This is one of the most important parameters that affects the consumption of RAM and performance, which needs to be optimized. MySQL tries to put everything that is indexed in the key buffer, so this parameter brings tremendous performance. The SQL query will be submitted directly from the RAM. I can not say what size you should set for key buffer, because only you know how much RAM you have free.
If you make the same requests twice in a row, the result is placed in the query cache, so mysql does not have to do the query again. If you are going to increase performance, then this parameter can be of great use, but memory consumption will increase. Therefore, you need to set this parameter not too huge, but not too small, that is, as much as your website needs.
Below are three variables that affect how your query cache works:
query_cache_size
query_cache_limit
query_cache_type
This is an optional parameter. If you have already limited the number of apache processes, then everything is already fine. If not, and you need to process thousands of users simultaneously, you need to increase the value of this parameter.
Each time you access a table, MySQL loads the table reference as one entry in the table cache. This is done for each parallel access to the table, it is really important for performance, it is insignificant to use memory. You can constantly increase the table cache, but then you will limit yourself to the limit on the number of open files in your operating system, so keep this in mind. If the table cache is too small, mysql will puke at you, you do not want it.
Below is the correct my.cnf, which I optimized on my VPS with the lowest tariff plan.
My my.cnf
[mysqld]
port = 3306
socket = /var/lib/mysql/mysql.sock
skip-locking
key_buffer = 16K
max_allowed_packet = 1M
table_cache = 4
sort_buffer_size = 64K
read_buffer_size = 256K
read_rnd_buffer_size = 256K
net_buffer_length = 2K
thread_stack = 64K
# For low memory, InnoDB should not be used so keep skip-innodb uncommented unless required
skip-innodb
# Uncomment the following if you are using InnoDB tables
#innodb_data_home_dir = /var/lib/mysql/
#innodb_data_file_path = ibdata1:10M:autoextend
#innodb_log_group_home_dir = /var/lib/mysql/
#innodb_log_arch_dir = /var/lib/mysql/
# You can set .._buffer_pool_size up to 50 - 80 %
# of RAM but beware of setting memory usage too high
#innodb_buffer_pool_size = 16M
#innodb_additional_mem_pool_size = 2M
# Set .._log_file_size to 25 % of buffer pool size
#innodb_log_file_size = 5M
#innodb_log_buffer_size = 8M
#innodb_flush_log_at_trx_commit = 1
#innodb_lock_wait_timeout = 50
[mysqldump]
quick
max_allowed_packet = 16M
[mysql]
no-auto-rehash
# Remove the next comment character if you are not familiar with SQL
#safe-updates
[isamchk]
key_buffer = 8M
sort_buffer_size = 8M
[myisamchk]
key_buffer = 8M
sort_buffer_size = 8M
[mysqlhotcopy]
interactive-timeout
I found Percona, which provides a free MySQL configuration and helps to choose the best features of MySQL server for maximum performance, and also save time, preventing the occurrence of motives and risks that may arise when self-configuring my.cnf.
MySQL stores statistics that help determine the best values to use. In addition, there are two convenient utilities that you can use to read this statistics and output in a clear format: tuning-primer.sh and mysqltuner.pl.
These scripts will allow you to monitor your MySQL server, and after that you will provide a hint about the parameters that need to be configured on your server.
PHP does not use memory very intensively, so I do not think that you need to worry much about memory consumption for these processes, if your application does not need it, but even if optimization is necessary, there will not be a significant reduction in consumed memory. But I researched and then found several settings for the PHP configuration, which reduce the memory consumption of the web server.
; Limit the memory to 40M should be fine for barebones WordPress
memory_limit = 48M
realpath_cache_ttl=300
realpath_cache_size=1M
Install PHP Cache, for example, such as, Alternative PHP Cache. PHP cache will store the compiled PHP scripts in such a way that they will be reused without compilation and, accordingly, will not create a load:
# pecl install apc
My php.ini
[APC]
extension=apc.so
apc.enabled=1
apc.shm_segments=1
;32M per WordPress install
apc.shm_size=128M
;Relative to the number of cached files (you may need to watch your stats for a day or two to find out a good number)
apc.num_files_hint=7000
;Relative to the size of WordPress
apc.user_entries_hint=4096
;The number of seconds a cache entry is allowed to idle in a slot before APC dumps the cache
apc.ttl=7200
apc.user_ttl=7200
apc.gc_ttl=3600
;Setting this to 0 will give you the best performance, as APC will
;not have to check the IO for changes. However, you must clear
;the APC cache to recompile already cached files. If you are still
;developing, updating your site daily in WP-ADMIN, and running W3TC
;set this to 1
apc.stat=1
;This MUST be 0, WP can have errors otherwise!
apc.include_once_override=0
;Only set to 1 while debugging
apc.enable_cli=0
;Allow 2 seconds after a file is created before it is cached to prevent users from seeing half-written/weird pages
apc.file_update_protection=2
;Leave at 2M or lower. WordPress does't have any file sizes close to 2M
apc.max_file_size=2M
;Ignore files
apc.filters = "/var/www/apc.php"
apc.cache_by_default=1
apc.use_request_time=1
apc.slam_defense=0
apc.mmap_file_mask=/var/www/temp/apc.XXXXXX
apc.stat_ctime=0
apc.canonicalize=1
apc.write_lock=1
apc.report_autofilter=0
apc.rfc1867=0
apc.rfc1867_prefix =upload_
apc.rfc1867_name=APC_UPLOAD_PROGRESS
apc.rfc1867_freq=0
apc.rfc1867_ttl=3600
apc.lazy_classes=0
apc.lazy_functions=0
Another thing that can be a good idea for a blog on a small server is to put it in front of a static HTTP-cache, for example, Varnish. What can really increase your scalability. The Varnish configuration is a separate large article that requires a separate topic.
I posted the configuration of my web server openly to prove that you can achieve high performance even from the cheapest VPS container with 512MB RAM and 1Ghz CPU. I use Ubuntu 14.04 LTS, LAMP, Varnish, APC Cache to host 3 web sites, made on WordPress (not multi-site) with a traffic of 10k per day.
Comments are closed.
Recent Comments