36

I'm currently using a Joyent Accelerator to host my webapps, and it's working fine, however I need to reduce costs so I'm downgrading my current plan and that imposes some new memory limits (256M rss, 512M swap). I wasn't too far over them yesterday, but after restarting Apache several times today, I'm now 411M rss, 721M swap (prstat -Z -s cpu).

Searching in Server Fault only gives me lots of ways and specific tools to monitor the server, but no advice on how to reduce/optimize it's memory usage. I've also seen this question, but I don't think it's good for this particular (or may I say generic?) situation.

The server is running Solaris on a shared CPU, and I'm using a Apache + MySQL + PHP stack.

I'm interested in knowing the steps one can take to troubleshot this and solve the issues. However, I'm also running out of time to lower my memory foot print and downgrade the plan before the current ends, so anything that can make magic and save the day is welcome as well :)

lima
  • 797
  • 1
  • 8
  • 14
  • 1
    I just wanted to comment that although I had learned about these settings myself from googling, it turned out that I was changing settings in one file, but a different config file that was being loaded later on was actually silently overriding my settings! Once I discovered that, setting the prefork MPM settings and a few other things worked wonders to keep process count and memory usage under control, swapping to a minimum. Hope this info helps others, especially those running Gentoo on their servers. – Pistos Nov 27 '09 at 00:57

8 Answers8

23

Thanks everyone for your answers! Following your suggestions I've been able to reduce my memory usage to 195M SWAP and 108M RSS, without touching my code (I'll definitely optimize it soon, but this was supposed to be a solution to get me out of trouble fast).

Here's the list of things I did:

Got rid of the wildcard used in VirtualHost entries. Instead of *:80 and *:443, I used the real IP of my server.

Changed Apache's prefork MPM. These are the values I ended up using:

StartServers           1
MinSpareServers        1 
MaxSpareServers        5 
ServerLimit           16
MaxClients            16
MaxRequestsPerChild    0
ListenBacklog        100

These are by no means magical numbers. I've spent some time trying different values and combination, and then testing them against the real usage of my server and everyone should do the same in their enviroment. For the record, my server receives close to 2M pvs/month, serving both dynamic pages and assets at a regular rate - no digg effect. The intention, again, was to reduce the memory footprint, not to improve performance or HA.

Reference:

Tunned down Apache's KeepAlive. By setting KeepAliveTimeout to a lower value (2 in my case) I can expect less server processes just waiting on connections with idle clients that may not request any more content.

Reference: http://httpd.apache.org/docs/2.0/mod/core.html#keepalivetimeout

Removed MySQL's unused module. I added skip-innodb to MySQL's my.cnf. Massive memory consumption reduction.


There are also some remarkable good suggestions that I couldn't personally do:

  • Remove PHP modules you do not need. The PHP on my server has most mods already compiled, I'll probably try my own minimal PHP on other VPS.
  • Switch to nginx with php-fastcgi. That's another good advice that I'll be trying soon, but right now I can't risk the downtime.
lima
  • 797
  • 1
  • 8
  • 14
  • I am running nginx and php-fastcgi (LEMP) and am running into similar memory issues ... on a 256MB server I find that php-fastcgi works well with PHP_FCGI_CHILDREN=5 and PHP_FCGI_MAX_REQUESTS=333 ... these values are a good starting point! – farinspace Jul 21 '10 at 20:52
  • `Got rid of the wildcard used in VirtualHost entries` does that actually help in any meaningful way? I was under the impression that wouldn't make a difference. – Mahn Oct 01 '13 at 12:34
  • @Mahn - it doesn't help with Memory, but it improves the CPU usage, which is a good thing in a low memory environment – jsnfwlr Feb 17 '14 at 00:11
  • "Switch to nginx with php-fastcgi" --- A less drastic yet effective option if you want to keep Apache2 would be: Apache2 + mod_proxy_fcgi + mod_mpm_event. mpm_event is similar to nginx. Use that to connect to php-fpm. See https://dracony.org/stop-using-php-fpm-to-argue-using-nginx-vs-apache/ – James Johnston Jun 13 '16 at 04:27
6

I found this article on low-memory configurations for Apache and MySQL

To be very useful in laying out the configuration changes needed for low memory configurations. I tweaked them for my own situation but they should give you the tools needed to find the best fit for your environment

Chris S
  • 77,337
  • 11
  • 120
  • 212
Kevin Kuphal
  • 9,064
  • 1
  • 34
  • 41
4

You're going to need to limit how many apache server processes are running, and being as close to the limit as you are, you're not going to be able to handle very much peaky traffic. Having a web server that's maxed out under normal usage is generally a Bad Idea (tm), as web traffic is nice and low for the most part until you get slashdotted or digged or fireballed or whatever.

The main issues are the number of apache processes that are running at any one point -- assuming prefork here, since I've only deployed PHP applications and PHP is not threadsafe. I don't have experience dimensioning the worker MPM. There are some items that are in shared memory, and some items that are in each process's memory.

You can reduce the total memory footprint by leaving out shared modules that you don't need. Basically, Apache comes configured from most hosts to do just about everything under the sun. If you're not using mod_userdir, then comment it out of your apache config. Just be careful how much you remove, because some of the things you may need or their dependencies are not intuitive! All of the modules should be documented on the apache.org website. The per process footprint is harder to get smaller; most apache configurations these days only come with the four essential modules compiled in. Beyond those four modules, most of the memory usage comes from either leaks or application RAM that's not garbage collected effectively, which is why you might want to set the number of requests handled by each process low.

You really want to keep your memory usage in RAM itself and not go into swap. Swap means I/O. I/O is slow and will drive your CPU usage through the roof as processes block while waiting for something to get shuffled out of swap.

Karl Katzke
  • 2,596
  • 1
  • 21
  • 24
  • 1
    Thanks for the advice Karl! Is there a way to prevent the server from using the Swap? Because after reducing the memory usage, I'm not over my RAM anymore, but it's still showing SWAP memory been used. – lima Jun 07 '09 at 14:54
  • @fandelost It doesn't really matter that swap is being used, it's when things are being paged in and out of swap that is bad. Your operating system might be swapping out instructions or data from processes that aren't running very often when there is time to do so because it thinks (and is often right) that those instructions and data are better off there. – Patrick James McDougle Feb 06 '13 at 14:16
2

For apache, remove the modules you do not use, as they just use additional memory. For MySQL, remove innodb/bbdb if you do not use them, and remove PHP modules you do not need.

Next you should configure apache MaxClients based on the size of one process and the amount of memory you want to give apache. Same goes for max connections on MySQL (I recommend the excellent MySQL Tuning Primer Script.

If you have control over your PHP app, make sure it doesn't use too much memory (e.g. in variables, especially static ones).

If you want to go further, you can replace apache+mod_php with nginx+fcgi setup, which will probably result in further memory reduction.

One last thing - you really don't want to swap on a web server. Just a little, to remove the unneeded stuff, but swapping regularily on a web server will result in a non-responsive web site.

yhager
  • 133
  • 5
  • Thanks for your advice yhager, I'm trying tuning-primer.sh but I get the following error: "syntax error at line 94: `cnf_socket=$' unexpected". Any ideas? – lima Jun 06 '09 at 17:06
  • Could be related to the shell. As this script is probably Linux related, try to change the first line to point to bash, instead of /bin/sh. I hope you can get bash installed on Solaris, but I can't help with that... – yhager Jun 07 '09 at 15:53
2

Since you already met your target, here's few extra:

Since you removed all unnecessery php modules, you could to the same for apache. By default (depending on the installation thou) apache loads quite a bunch of extra modules and most of them are not really required for normal day to day usage. For example, there are bunch of authentication modules that are always loaded. deflate is typically not required unless you are trying to limit your bandwidth usage. Autoindex & status goes are also questionable.

And another one is that you can limit the amount of memory available for php in php.ini: memory_limit=xxxM

rasjani
  • 365
  • 2
  • 6
0

You could of course limit the number of processes apache can fork, however this would only work as a sudo-hard limit on your memory usage. From a lower level point of view you can use plimit to restrict the resources available to a process. Apply this to the parent and child processes inherit I believe.

However from a web server configuration point of view it can come down to how your code runs really! But bear in mind small things like using .htaccess files use more resources than using central apache configuration files (as they are read every time a request comes in, leading to greater overhead), something which is signification in large web sites.

Coops
  • 5,967
  • 1
  • 31
  • 52
0

One thing that might help memory growth over time is setting the httpd keepalive lower, but I'd test that carefully in case your application needs longer lived processes.

D.F.
  • 646
  • 3
  • 6
0

The server is running Solaris on a shared CPU, and I'm using a Apache + MySQL + PHP stack.

I don't have experience with Solaris, but the best thing you can do is to not use Apache/mod_php.

  • Switch to nginx with php-fastcgi.
  • Recompile php to use the minimal amount of plugins.
  • Get rid of unnecessary processes like ntpd (use ntpdate), ftp (use scp) etc...
Unknown
  • 1,675
  • 6
  • 20
  • 27