05.10.06

Optimizing MySQL and Apache for Low Memory Usage, Part 1

Posted in General at 2:41 pm by matt

MySQL and Apache can consume quite a bit of memory, if you’re not careful. This post discusses how to reduce the amount of memory they use without killing performance. The caveat, of course, is that you’re not going to be able to run a site with a large database and large amount of traffic with these settings. I’m going to try to explain the WHY more than the WHAT. All of this is in conjunction with my goal of reducing the amount of ram I use on my Xen based virtual server, as discussed previously in, Low Memory Computing.
Before I begin, I’d like to say that you should also look at various system utilities that consume ram. Services like FTP and SMTP can and should be passed off to xinetd. Also, you should look at shells besides bash, such as dash. And, if you’re really serious about low memory, you might look at using something like BusyBox, which brings you into the realm of real embedded systems. Personally, I just want to get as much as I can out of a standard linux distribution. If I need more horsepower, I want to be able to move to bigger, faster virtual machines and/or dedicated servers. For now, optimizing a small virtual machine will do.
First off, Apache. My first statement is, if you can avoid it, try to. Lighttpd and thttpd are both very good no frills webservers, and you can run lighttpd with PHP. Even if you’re running a high volume site, you can seriously gain some performance by passing off static content (images and javascript files, usually) to a lightweight, super-fast HTTPd server such as Lighttpd.

The biggest problem with Apache is the amount of ram is uses. I’ll discuss the following techniques for speeding up Apache and lowering the ram used.

  • Loading Fewer Modules
  • Handle Fewer Simultaneous Requests
  • Recycle Apache Processes
  • Use KeepAlives, but not for too long
  • Lower your timeout
  • Log less
  • Don’t Resolve Hostnames
  • Don’t use .htaccess

Loading Fewer Modules

First things first, get rid of unnecessary modules. Look through your config files and see what modules you might be loading. Are you using CGI? Perl? If you’re not using modules, by all means, don’t load them. That will save you some ram, but the BIGGEST impact is in how Apache handles multiple requests.

Handle Fewer Simultaneous Requests

The more processes apache is allowed to run, the more simultaneous requests it can serve. As you increase that number, you increase the amount of ram that apache will take. Looking at TOP would suggest that each apache process takes up quite a bit of ram. However, there are a lot of shared libraries being used, so you can run some processes, you just can’t run a lot. With Debian 3.1 and Apache2, the following lines are the default:

StartServers 5
MinSpareServers 5
MaxSpareServers 10
MaxClients 20
MaxRequestsPerChild 0

I haven’t found documentation on this, but prefork.c seems to be the module that’s loaded to handle things w/ Apache2 and Debian 3.1. Other mechanisms could or could not be much more memory efficient, but I’m not digging that deep, yet. I’d like to know more, though, so post a comment and let me know. Anyway, the settings that have worked for me are:

StartServers 1
MinSpareServers 1
MaxSpareServers 5
MaxClients 5
MaxRequestsPerChild 300

What I’m basically saying is, “set the maximum amount of requests that this server can handle at any one time to 5.” This is pretty low, and I wouldn’t try to do this on a high volume server. However, there is something you can and should do on your webservers to get the most out of them, whether you’re going for low memory or not. That is tweak the keepalive timeout.

Recycle Apache Processes

If you noticed, I changed the MaxRequestsPerChild variable to 500, from 0. This variable tells Apache how many requests a given child process can handle before it should be killed. You want to kill processes, because different page requests will allocate more memory. If a script allocates a lot of memory, the Apache process under which it runs will allocate that memory, and it won’t let it go. If you’re bumping up against the memory limit of your system, this could cause you to have unnecessary swapping. Different people use different settings here. How to set this is probably a function of the traffic you receive and the nature of your site. Use your brain on this one.

Use KeepAlives, but not for too long

Keepalives are a way to have a persistent connection between a browser and a server. Originally, HTTP was envisioned as being “stateless.” Prior to keepalive, every image, javascript, frame, etc. on your pages had to be requested using a separate connection to the server. When keepalives came into wide use with HTTP/1.1, web browsers were able to keep a connection to a server open, in order to transfer multiple files across that same connection. Fewer connections, less overhead, more performance. There’s one thing wrong, though. Apache, by default, keeps the connections open for a bit too long. The default seems to be 15 seconds, but you can get by easily with 2 or 3 seconds.

This is saying, “when a browser stops requesting files, wait for X seconds before terminating the connection.” If you’re on a decent connection, 3 seconds is more than enough time to wait for the browser to make additional requests. The only reason I can think of for setting a higher KeepAliveTimeout is to keep a connection open for the NEXT page request. That is, user downloads page, renders completely, clicks another link. A timeout of 15 would be appropriate for a site that has people clicking from page to page, very often. If you’re running a low volume site where people click, read, click, etc., you probably don’t have this. You’re essentially taking 1 or more apache processes and saying, “for the next 15 seconds, don’t listen to anyone but this one guy, who may or may not actually ask for anything.” The server is optimizing one case at the expense of all the other people who are hopefully hitting your site.

Lower Your Timeout

Also, just in case, since you’re limiting the number of processes, you don’t want one to be “stuck” timing out for too long, so i suggest you lower your “normal” Timeout variable as well.

Log Less

If you’re trying to maximize performance, you can definitely log less. Modules such as Mod_Rewrite will log debugging info. If you don’t need the debugging info, get rid of it. The Rewrite log is set with the RewriteLog command. Also, if you don’t care about looking at certain statistics, you can choose to not log certain things, like the User-Agent or the Http-Referer. I like seeing those things, but it’s up to you.
Don’t Resolve Hostnames

This one’s easy. Don’t do reverse lookups inside Apache. I can’t think of a good reason to do it. Any self respecting log parser can do this offline, in the background.

HostnameLookups Off

Don’t Use .htaccess

You’ve probably seen the AllowOverride None command. This says, “don’t look for .htaccess files” Using .htaccess will cause Apache to 1) look for files frequently and 2) parse the .htaccess file for each request. If you need per-directory changes, make the changes inside your main Apache configuration file, not in .htaccess.
Well, that’s it for Part 1, I’ll be back soon with Part 2, where I’ll talk about MySQL optimization & possibly a few other things that crop up.

Credits:

I’d like to give credit to a few articles that were helpful in putting this information together.  I’m not a master at this, I’m just trying to compile lots of bits and pieces together into one place.  Thanks go to:

32 Comments »

  1. Christian said,

    May 11, 2006 at 1:24 pm

    Great article! I’m definitely going to put some of this into practice. I just moved to a low-memory VPS and I am feeling the memory “crunch”. Looking forward to the MySQL followup.

  2. Emergent Properties » Serving Javascript and Images — Fast said,

    May 11, 2006 at 2:00 pm

    [...] Recently, I posted an article mainly about optimizing apache for low memory usage.  There, I noted that webservers like thttpd and lighttpd are really good at serving things fast.  I’ve been trying to optimize a site I’m playing with, and I’ve done a bit of analysis / work on using an alternative webserver. [...]

  3. Emergent Properties » Blog Archive » Article about apache and vps optimization said,

    May 15, 2006 at 12:06 pm

    [...] I just put an article about low memory apache and vps optimization up on my blog. [...]

  4. Craig said,

    May 19, 2006 at 6:46 am

    Lighttpd can handle bigger sites than apache… it’s designed for the C10K problem!

  5. Emergent Properties » Optimizing Apache and MySQL for Low Memory Usage, Part 2 said,

    June 5, 2006 at 4:39 pm

    [...] In Optimizing Apache and MySQL for Low Memory Usage, Part 1, I discussed some system tools and Apache optimization. I’ve also discussed mod_deflate, thttpd, and lighttpd in Serving Javascript and Images — Fast. Now, i’ll talk about MySQL. [...]

  6. Optimizing Apache for Low Memory Usage » Bogle’s Blog said,

    October 5, 2006 at 8:48 pm

    [...] With so little memory, the default Apache memory configuration in the Redhat distribution will enter a flaming death spiral of swapping under moderate load.  If you’re in that boat, you should read Optimizing MySQL and Apache for Low Memory Usage by Emergent Properties.  [...]

  7. links for 2006-10-11 « Vinny Carpenter’s blog said,

    October 11, 2006 at 5:20 pm

    [...] Emergent Properties » Optimizing MySQL and Apache for Low Memory Usage, Part 1 MySQL and Apache can consume quite a bit of memory, if you’re not careful. This post discusses how to reduce the amount of memory they use without killing performance. (tags: apache mysql optimization performance tuning hosting memory linux) [...]

  8. Vinny Carpenter’s blog · Daily del.icio.us for Oct 11, 2006 said,

    October 11, 2006 at 7:32 pm

    [...] Emergent Properties » Optimizing MySQL and Apache for Low Memory Usage, Part 1 MySQL and Apache can consume quite a bit of memory, if you’re not careful. This post discusses how to reduce the amount of memory they use without killing performance. (tags: apache mysql optimization performance tuning hosting memory linux) Tags:Java/J2EEBookmark this page at:These icons link to social bookmarking sites where readers can share and discover new web pages. [...]

  9. ross mclachlan » Optimising performance said,

    December 12, 2006 at 2:38 am

    [...] Optimising MySQL and Apache for low memory usage  [...]

  10. Saleesh said,

    January 8, 2007 at 11:03 pm

    Nice Article…It was quite helpful

  11. Optimizing MySQL and Apache for Low Memory Usage at Muzz said,

    January 23, 2007 at 4:33 am

    [...] Emergent Properties — Optimizing MySQL and Apache for Low Memory Usage, Part 1 [...]

  12. Steve said,

    February 7, 2007 at 4:12 am

    Really nice article! I’ve just tried to optimize my apace configuration, now it sounds good

  13. Krazy-J said,

    February 14, 2007 at 7:20 am

    GREAT !! Can’t recommend this further, although I would recommend setting:

    MaxSpareServers 5
    MaxClients 5

    To about 6-7

    but yeah, follow the above guide, CAN’T Go wrong..

  14. .bootstrap » Optimize MySQL for Low Memory Use said,

    March 27, 2007 at 11:52 pm

    [...] More on MySQL and Apache optimization and here [...]

  15. BitRatchet » Apache Memory Tips posted on Emergent Properties said,

    April 12, 2007 at 2:05 am

    [...] http://emergent.urbanpug.com/?p=60 [...]

  16. Peter said,

    June 8, 2007 at 10:27 am

    One thing I haven’t seen addressed is how to detect if the number of spare servers configured in apache2.conf is too low. Is there any way to tell?

  17. matt said,

    June 8, 2007 at 12:38 pm

    If it’s too low, browser requests will have to wait til there’s a spare. In other words, you’ll probably need to do some stress testing.

  18. Linux Machine » Blog Archive » Switching to "LLMP" for a more responsive server said,

    June 9, 2007 at 8:15 am

    [...] Lately I’ve been running into a few issues with Apache using up lots of RAM on my server and causing long load times for pages. I took into consideration a few tips I found (here), but I thought I would be better off replacing Apache as a whole. After looking at some alternatives, I decided on lighttpd. Since my operating system, CentOS, does not provide precompiled packages, I had to compile my own. The instructions on the Lighttpd wiki are fairly straightforward and easy (./configure, make, sudo make install, and then add it to your init scripts). [...]

  19. David George said,

    July 22, 2007 at 4:55 am

    > If it’s too low, browser requests will have to wait til there’s a spare.

    MaxSpareServers says how many warm daemons to keep hanging around for requests. The Apache listerner will still create new daemons on command but it will kill these children off after usage. MaxClients governs how many simultaneous requests can be handled. I would set this to higher than MaxSpareServers.

  20. Apache2 Low Memory Footprint | Cheer Factory - Technology, Outdoor and Design said,

    September 15, 2007 at 2:54 pm

    [...] I found this very useful for fine tuning my vps memory usage. [...]

  21. Because I Learn » Blog Archive » Saving RAM said,

    November 5, 2007 at 9:07 pm

    [...] I followed recommendations in this article because I’m having a Link-2 plan. Below is output of ‘top’ after my first optimization. [...]

  22. sk said,

    January 16, 2008 at 5:15 pm

    A quick test if you have enough meory for Apache and N servers

    StartServers N
    MinSpareServers N
    MaxSpareServers N

    I have only 128MB and use N=15

    Test with the following and observe swapping

    apache2 -k start; sleep 30; apache2 -k stop; vmstat 1

    Break when swapping ends… ;)

    Now try

    apache2 -k start; sleep 30; apache2 -k graceful-stop; vmstat 1

    Do “killall -s KILL apache2″ and weep…. ;-D

    A gracefull stop is costly.

  23. Vin0×64 » Archive du blog » Tuner Apache pour les petits serveurs pauvres en mémoire (1) said,

    April 15, 2008 at 1:25 pm

    [...] Partant de ce constat une rapide requète google sur le tuning de apache pour les configurations faibles en mémoire fait remonter le site: http://emergent.urbanpug.com/?p=60 dont je recommande la lecture. [...]

  24. Apache und MYSQL performanter machen | blog@Fabi said,

    July 27, 2008 at 7:46 am

    [...] Optimizing MySQL and Apache for Low Memory Usage, Part 1 [...]

  25. Not So Wise said,

    September 11, 2008 at 1:09 am

    [...] After LAMP you need to optimize Apache and mysql for a low memory server to work. This is what I have for my mysql config /etc/mysql/my.cnfCredits and further reading, this, this also this and that[client]port = [port number at your choice]socket = /var/run/mysqld/mysqld.sock[mysqld_safe]socket = /var/run/mysqld/mysqld.socknice = 0[mysqld]user = mysqlpid-file = /var/run/mysqld/mysqld.pidsocket = /var/run/mysqld/mysqld.sockport = [port number at your choice]basedir = /usrdatadir = /var/lib/mysqltmpdir = /tmplanguage = /usr/share/mysql/englishskip-external-lockingbind-address = 127.0.0.1## * Fine Tuning#skip-lockingkey_buffer = 16Kmax_allowed_packet = 1Mtable_cache = 4sort_buffer_size = 64Kread_buffer_size = 256Kread_rnd_buffer_size = 256Knet_buffer_length = 2Kthread_stack = 64K# For low memory, Berkeley DB should not be used# so keep skip-bdb# uncommented unless requiredskip-bdb# For low memory, InnoDB should not be used# so keep skip-innodb# uncommented unless requiredskip-innodb# make sure all parameters starting with innodb_ are commented out# unless you are using InnoDB tables[mysqldump]quickmax_allowed_packet = 16M[mysql]no-auto-rehash# Remove the next comment character if you are # not familiar with SQL#safe-updates[isamchk]key_buffer = 8Msort_buffer_size = 8M[myisamchk]key_buffer = 8Msort_buffer_size = 8M[mysqlhotcopy]interactive-timeoutFile apache2.confServerRoot “/etc/apache2″LockFile /var/lock/apache2/accept.lockPidFile /var/run/apache2.pidTimeout 60 # timeout was 300KeepAlive OnMaxKeepAliveRequests 100KeepAliveTimeout 3 StartServers 1 MinSpareServers 1 MaxSpareServers 5 MaxClients 50 MaxRequestsPerChild 1000 # was 5000User www-dataGroup www-data#ServerName 127.0.0.1ServerName your.domain.net AccessFileName .htaccess Order allow,deny Deny from allDefaultType text/plainHostnameLookups OffErrorLog /var/log/apache2/error.logLogLevel warnInclude /etc/apache2/mods-enabled/*.loadInclude /etc/apache2/mods-enabled/*.confInclude /etc/apache2/httpd.confInclude /etc/apache2/ports.confLogFormat “%h %l %u %t “%r” %>s %b “%{Referer}i” “%{User-Agent}i”" combinedLogFormat “%h %l %u %t “%r” %>s %b” commonLogFormat “%{Referer}i -> %U” refererLogFormat “%{User-agent}i” agentServerTokens FullServerSignature OnInclude /etc/apache2/conf.d/Include /etc/apache2/sites-enabled/Include /etc/phpmyadmin/apache.conf There are currently no comments. [...]

  26. Vlad said,

    September 20, 2008 at 11:54 pm

    Thanks! It works!

  27. seany said,

    December 19, 2008 at 11:20 am

    Hello,

    Our customers would find this article useful. With your permission, can we feature this article on our support forums, giving you proper credit and a link back?

    Thanks!

  28. UniversidadPeru said,

    August 7, 2009 at 12:13 pm

    Hi there! Followed your instructions, and now my virtual server literally is “on fire!” I was having services stopping and restarting abruptly when traffic spiked, and it was because memory was running out…

    I went from 712mb ram consumption to around 348mb with your tips, and the site is quite fast and responsive… Thanks!

  29. Alex said,

    November 8, 2009 at 7:55 pm

    Thanks a lot for this clear and straight to the point article. My server was regularly becoming totally unresponsive because Apache would go crazy and trigger memory pages swapping, but following your directives it seems that I have finally solved my problem. My memory usage has been divided by 3, and at the same time requests are being served much more rapidly.

  30. CooPs said,

    March 21, 2010 at 11:10 am

    I really doubt that turning off hostname resolving would increese performance even noticeably and I have a good reason for you right here on why you’d want it enabled: you can make access rules based on hostnames. If you know how DNS works you’d understand why it’s not a performance bump: All DNS lookups (even reverse lookups) are cached, and all OS do it locally. So for every unique IP it would only need to do the lookup once. After that the OS has the lookup cached in memory.

    Also .htaccess is very useful and I don’t see on how some file lookups could justify disabling it. I can only see why that would make sense in extreme cases: eg if you’re hosting some kind of file server with a lot of traffic and no special per directory rewriting or acceess control or applications running on it.

    If you’re really looking for conserving memory I would recommend turning KeepAlive off completly. Having it enabled gives clients the ability to lock your children and with a maximum ammount of children set, that’s a very bad idea unless you actually want people to time out. Turning it off worked great for me.

  31. Tom V said,

    March 31, 2010 at 1:54 am

    Very useful. I’ve had to configure a low RAM server and these tips have helped incredibly.

  32. VPS Hosting with HyperVM and Kloxo said,

    March 8, 2011 at 12:02 am

    [...] to reduce the memory load. If that’s not enough for you, also have a look at these pages for Apache and MySQL [...]

Leave a Comment