Skip to content

Entries from December 2008.

High Virtual Memory Usage on Linux (OpenVZ) problem: solved

Few days ago I bought new small VPS box (OpenVZ, 128 MB RAM) in order to place there a new monitoring node of my site monitoring system. Such small amount of RAM is a challenge for operating system optimisation techniques (OpenVZ doesn't have "swap" as Xen does). First of all I discovered that apache2-mpm-worker (Apache implementation that uses threads) consumes more memory (100MB) than the classic version that use separate processes (20MB). I had to switch to apache2-mpm-prefork version then. Next unpleasant surprise: small Python app eats 100MB of virtual memory! I checked that virtual (not resident) memory is taken into account by VPS. I applied some tools to locate memory bottleneck, but without success. Next I added logs with current memory usage to track call that causes big memory consumption. I tracked the following line:

server = WSGIServer(app)

is guilty for high memory increase. After few minutes of googling I located problem: default stack size for a thread. Details:
  1. This line creates few threads to handle concurrent calls
  2. Stack size is counted towards virtual memory
  3. Default stack size is very high on Linux (8MB)
  4. Every thread uses separate stack
=> multi threaded application will use at least number_of_threads * 8MB virtual memory! First solution: use limits.conf file. I altered /etc/security/limits.conf file and changed default stack size. But I couldn't make this change to alter Python scripts called from Apache (any suggestions why?). Second (working) solution: lower default stack size using ulimit. For processes launched from Apache I altered /etc/init.d/apache2 script and added:

ulimit -s 128

Now every thread (in apache / Python application) will use only 128 kB of virtual memory (I lowered VSZ from 70 MB to 17 MB this way). Now I have additional space to enlarge MySQL buffers to make DB operations faster. UPDATE: There's better place to inject ulimit system-wide: you can insert this call in:

/etc/init.d/rc

script. Then ulimit will be applied to all daemons (as Apache) and all login sessions.