Rails memory usage case study

Stumbled across this interesting thread earlier today.

The remainder of this post assumes the following:

  • Production environment
  • Mongrel does not leak memory (Zed would have told you so if it did)
  • Latest stable Mongrel and FastThread
  • You're not using the usual culprits, RMagick and Ferret
  • You're not running any patched GC

The system

My staging system is CentOS 4 (64 bit) with 2GB RAM and runs 5 x PHP FCGI's, Nginx, Memcached, MySQL 5 and 8 x Mongrels. Staging Mongrel traffic only, medium traffic PHP forum.

Linux memory management

Here's a snapshot after just firing up mongrel_cluster:


[bookings@somehost ~]$  free -m
             total       used       free     shared    buffers     cached
Mem:          2003       1390        612          0        107        152
-/+ buffers/cache:       1131        871
Swap:         1992         81       1910

The -/+ buffers/cache is how much memory I have available, swap space is pretty much stock defaults for CentOS.

Here's a process snapshot of the Mongrels ( all idle, no traffic, no warm up, yet ):


[bookings@somehost ~]$ ps aux | grep mongrel
USER       PID %CPU %MEM   VSZ  RSS TTY      STAT START   TIME COMMAND
mongrel   7659  2.7  4.8 139080 99840 ?      S    11:35   0:15 /usr/local/bin/ruby /usr/local/bin/mongrel_rails start -d -e production -p 8000 -a 127.0.0.1 -P /u/apps/bookings/current/log/mongrel.8000.pid -c /u/apps/bookings/current --user mongrel --group mongrel
mongrel   7662  2.6  4.8 138648 99408 ?      S    11:35   0:15 /usr/local/bin/ruby /usr/local/bin/mongrel_rails start -d -e production -p 8001 -a 127.0.0.1 -P /u/apps/bookings/current/log/mongrel.8001.pid -c /u/apps/bookings/current --user mongrel --group mongrel
mongrel   7665  2.7  4.6 134836 95560 ?      S    11:35   0:15 /usr/local/bin/ruby /usr/local/bin/mongrel_rails start -d -e production -p 8002 -a 127.0.0.1 -P /u/apps/bookings/current/log/mongrel.8002.pid -c /u/apps/bookings/current --user mongrel --group mongrel
mongrel   7668  2.7  4.6 133684 94408 ?      S    11:35   0:15 /usr/local/bin/ruby /usr/local/bin/mongrel_rails start -d -e production -p 8003 -a 127.0.0.1 -P /u/apps/bookings/current/log/mongrel.8003.pid -c /u/apps/bookings/current --user mongrel --group mongrel
mongrel   7671  2.7  4.7 135744 96540 ?      S    11:35   0:15 /usr/local/bin/ruby /usr/local/bin/mongrel_rails start -d -e production -p 8004 -a 127.0.0.1 -P /u/apps/bookings/current/log/mongrel.8004.pid -c /u/apps/bookings/current --user mongrel --group mongrel
mongrel   7674  2.7  4.7 135768 96540 ?      S    11:35   0:15 /usr/local/bin/ruby /usr/local/bin/mongrel_rails start -d -e production -p 8005 -a 127.0.0.1 -P /u/apps/bookings/current/log/mongrel.8005.pid -c /u/apps/bookings/current --user mongrel --group mongrel
mongrel   7677  2.7  4.6 133644 94404 ?      S    11:35   0:15 /usr/local/bin/ruby /usr/local/bin/mongrel_rails start -d -e production -p 8006 -a 127.0.0.1 -P /u/apps/bookings/current/log/mongrel.8006.pid -c /u/apps/bookings/current --user mongrel --group mongrel
mongrel   7680  2.7  4.8 139284 100044 ?     S    11:36   0:15 /usr/local/bin/ruby /usr/local/bin/mongrel_rails start -d -e production -p 8007 -a 127.0.0.1 -P /u/apps/bookings/current/log/mongrel.8007.pid -c /u/apps/bookings/current --user mongrel --group mongrel

Virtual Size

The Virtual Size (VIRT in 'top' output) for the process with PID 7659 is 139MB.

  • Total memory used by the process
  • INCLUDING any shared libraries (FreeImage, MySQL, Zlib etc.)
  • INCLUDING memory shared with other processes

A more verbose example of exactly which shared libs we require ( Rails AND Mongrel ):


[root@somehost bookings]# pmap -d 7659
7659:   /usr/local/bin/ruby /usr/local/bin/mongrel_rails start -d -e production -p 8000 -a 127.0.0.1 -P /u/apps/bookings/current/log/mongrel.8000.pid -c /u/apps/bookings/current --user mongrel --group mongrel
Address           Kbytes Mode  Offset           Device    Mapping
0000000000400000     780 r-x-- 0000000000000000 008:00003 ruby
00000000005c3000       8 rw--- 00000000000c3000 008:00003 ruby
00000000005c5000   43380 rwx-- 00000000005c5000 000:00000   [ anon ]
0000002a95556000      16 rw--- 0000002a95556000 000:00000   [ anon ]
0000002a95563000     404 rw--- 0000002a95563000 000:00000   [ anon ]
0000002a955c9000     704 rw--- 0000002a955c9000 000:00000   [ anon ]
0000002a95679000      12 r-x-- 0000000000000000 008:00003 digest.so
0000002a9567c000    1020 ----- 0000000000003000 008:00003 digest.so
0000002a9577b000       4 rw--- 0000000000002000 008:00003 digest.so
0000002a9577c000     232 r-x-- 0000000000000000 008:00003 openssl.so
0000002a957b6000    1020 ----- 000000000003a000 008:00003 openssl.so
0000002a958b5000      12 rw--- 0000000000039000 008:00003 openssl.so
0000002a958b8000       4 r-x-- 0000000000000000 008:00003 fcntl.so
0000002a958b9000    1020 ----- 0000000000001000 008:00003 fcntl.so
0000002a959b8000       4 rw--- 0000000000000000 008:00003 fcntl.so
0000002a959b9000    3548 rw--- 0000002a959b9000 000:00000   [ anon ]
0000002a95d30000      20 r-x-- 0000000000000000 008:00003 stringio.so
0000002a95d35000    1020 ----- 0000000000005000 008:00003 stringio.so
0000002a95e34000       4 rw--- 0000000000004000 008:00003 stringio.so
0000002a95e35000     112 r-x-- 0000000000000000 008:00003 syck.so
0000002a95e51000    1020 ----- 000000000001c000 008:00003 syck.so
0000002a95f50000       8 rw--- 000000000001b000 008:00003 syck.so
0000002a95f52000      40 r-x-- 0000000000000000 008:00003 socket.so
0000002a95f5c000    1024 ----- 000000000000a000 008:00003 socket.so
0000002a9605c000       4 rw--- 000000000000a000 008:00003 socket.so
0000002a9605d000      24 r-x-- 0000000000000000 008:00003 http11.so
0000002a96063000    1024 ----- 0000000000006000 008:00003 http11.so
0000002a96163000       4 rw--- 0000000000006000 008:00003 http11.so
0000002a96164000      16 r-x-- 0000000000000000 008:00003 fastthread.so
0000002a96168000    1020 ----- 0000000000004000 008:00003 fastthread.so
0000002a96267000       4 rw--- 0000000000003000 008:00003 fastthread.so
0000002a96268000      16 r-x-- 0000000000000000 008:00003 thread.so
0000002a9626c000    1020 ----- 0000000000004000 008:00003 thread.so
0000002a9636b000       4 rw--- 0000000000003000 008:00003 thread.so
0000002a9636c000      36 r-x-- 0000000000000000 008:00003 zlib.so
0000002a96375000    1020 ----- 0000000000009000 008:00003 zlib.so
0000002a96474000       4 rw--- 0000000000008000 008:00003 zlib.so
0000002a96475000       8 r-x-- 0000000000000000 008:00003 etc.so
0000002a96477000    1024 ----- 0000000000002000 008:00003 etc.so
0000002a96577000       4 rw--- 0000000000002000 008:00003 etc.so
0000002a96579000    4104 rw--- 0000002a96579000 000:00000   [ anon ]
0000002a96987000      40 r-x-- 0000000000000000 008:00003 libnss_files-2.3.4.so
0000002a96991000    1024 ----- 000000000000a000 008:00003 libnss_files-2.3.4.so
0000002a96a91000       8 rw--- 000000000000a000 008:00003 libnss_files-2.3.4.so
0000002a96a93000      16 r-x-- 0000000000000000 008:00003 strscan.so
0000002a96a97000    1024 ----- 0000000000004000 008:00003 strscan.so
0000002a96b97000       4 rw--- 0000000000004000 008:00003 strscan.so
0000002a96b98000     240 r-x-- 0000000000000000 008:00003 nkf.so
0000002a96bd4000    1024 ----- 000000000003c000 008:00003 nkf.so
0000002a96cd4000      16 rw--- 000000000003c000 008:00003 nkf.so
0000002a96cd8000       4 rw--- 0000002a96cd8000 000:00000   [ anon ]
0000002a96cd9000      40 r-x-- 0000000000000000 008:00003 bigdecimal.so
0000002a96ce3000    1024 ----- 000000000000a000 008:00003 bigdecimal.so
0000002a96de3000       4 rw--- 000000000000a000 008:00003 bigdecimal.so
0000002a96de5000    7384 rw--- 0000002a96de5000 000:00000   [ anon ]
0000002a9751b000       4 r-x-- 0000000000000000 008:00003 md5.so
0000002a9751c000    1020 ----- 0000000000001000 008:00003 md5.so
0000002a9761b000       4 rw--- 0000000000000000 008:00003 md5.so
0000002a9761c000      16 r-x-- 0000000000000000 008:00003 cparse.so
0000002a97620000    1020 ----- 0000000000004000 008:00003 cparse.so
0000002a9771f000       4 rw--- 0000000000003000 008:00003 cparse.so
0000002a97720000      16 r-x-- 0000000000000000 008:00003 iconv.so
0000002a97724000    1020 ----- 0000000000004000 008:00003 iconv.so
0000002a97823000       4 rw--- 0000000000003000 008:00003 iconv.so
0000002a97824000   13292 rw--- 0000002a97824000 000:00000   [ anon ]
0000002a9851f000       4 r-x-- 0000000000000000 008:00003 sha1.so
0000002a98520000    1020 ----- 0000000000001000 008:00003 sha1.so
0000002a9861f000       4 rw--- 0000000000000000 008:00003 sha1.so
0000002a98620000   23924 rw--- 0000002a98620000 000:00000   [ anon ]
0000002a99d7d000     916 r-x-- 0000000000000000 008:00003 mysql.so
0000002a99e62000    1020 ----- 00000000000e5000 008:00003 mysql.so
0000002a99f61000    1036 rw--- 00000000000e4000 008:00003 mysql.so
0000002a9a064000       8 rw--- 0000002a9a064000 000:00000   [ anon ]
000000320ac00000      84 r-x-- 0000000000000000 008:00003 ld-2.3.4.so
000000320ad14000       8 rw--- 0000000000014000 008:00003 ld-2.3.4.so
000000320ae00000    1196 r-x-- 0000000000000000 008:00003 libc-2.3.4.so
000000320af2b000    1024 ----- 000000000012b000 008:00003 libc-2.3.4.so
000000320b02b000       8 r---- 000000000012b000 008:00003 libc-2.3.4.so
000000320b02d000      12 rw--- 000000000012d000 008:00003 libc-2.3.4.so
000000320b030000      16 rw--- 000000320b030000 000:00000   [ anon ]
000000320b100000       8 r-x-- 0000000000000000 008:00003 libdl-2.3.4.so
000000320b102000    1020 ----- 0000000000002000 008:00003 libdl-2.3.4.so
000000320b201000       8 rw--- 0000000000001000 008:00003 libdl-2.3.4.so
000000320b300000     532 r-x-- 0000000000000000 008:00003 libm-2.3.4.so
000000320b385000    1020 ----- 0000000000085000 008:00003 libm-2.3.4.so
000000320b484000       8 rw--- 0000000000084000 008:00003 libm-2.3.4.so
000000320b500000      76 r-x-- 0000000000000000 008:00003 libz.so.1.2.1.2
000000320b513000    1020 ----- 0000000000013000 008:00003 libz.so.1.2.1.2
000000320b612000       4 rw--- 0000000000012000 008:00003 libz.so.1.2.1.2
000000320b700000      68 r-x-- 0000000000000000 008:00003 libresolv-2.3.4.so
000000320b711000    1024 ----- 0000000000011000 008:00003 libresolv-2.3.4.so
000000320b811000       8 rw--- 0000000000011000 008:00003 libresolv-2.3.4.so
000000320b813000       8 rw--- 000000320b813000 000:00000   [ anon ]
000000320b900000      20 r-x-- 0000000000000000 008:00003 libcrypt-2.3.4.so
000000320b905000    1020 ----- 0000000000005000 008:00003 libcrypt-2.3.4.so
000000320ba04000       8 rw--- 0000000000004000 008:00003 libcrypt-2.3.4.so
000000320ba06000     184 rw--- 000000320ba06000 000:00000   [ anon ]
000000320bd00000      80 r-x-- 0000000000000000 008:00003 libnsl-2.3.4.so
000000320bd14000    1020 ----- 0000000000014000 008:00003 libnsl-2.3.4.so
000000320be13000       8 rw--- 0000000000013000 008:00003 libnsl-2.3.4.so
000000320be15000       8 rw--- 000000320be15000 000:00000   [ anon ]
000000320bf00000       8 r-x-- 0000000000000000 008:00003 libcom_err.so.2.1
000000320bf02000    1020 ----- 0000000000002000 008:00003 libcom_err.so.2.1
000000320c001000       4 rw--- 0000000000001000 008:00003 libcom_err.so.2.1
000000320c300000     436 r-x-- 0000000000000000 008:00003 libkrb5.so.3.2
000000320c36d000    1024 ----- 000000000006d000 008:00003 libkrb5.so.3.2
000000320c46d000      16 rw--- 000000000006d000 008:00003 libkrb5.so.3.2
000000320c500000    1080 r-x-- 0000000000000000 008:00003 libcrypto.so.0.9.7a
000000320c60e000    1024 ----- 000000000010e000 008:00003 libcrypto.so.0.9.7a
000000320c70e000     120 rw--- 000000000010e000 008:00003 libcrypto.so.0.9.7a
000000320c72c000      16 rw--- 000000320c72c000 000:00000   [ anon ]
000000320c800000     136 r-x-- 0000000000000000 008:00003 libk5crypto.so.3.0
000000320c822000    1020 ----- 0000000000022000 008:00003 libk5crypto.so.3.0
000000320c921000       8 rw--- 0000000000021000 008:00003 libk5crypto.so.3.0
000000320ca00000      84 r-x-- 0000000000000000 008:00003 libgssapi_krb5.so.2.2
000000320ca15000    1024 ----- 0000000000015000 008:00003 libgssapi_krb5.so.2.2
000000320cb15000       4 rw--- 0000000000015000 008:00003 libgssapi_krb5.so.2.2
000000320ce00000     216 r-x-- 0000000000000000 008:00003 libssl.so.0.9.7a
000000320ce36000    1024 ----- 0000000000036000 008:00003 libssl.so.0.9.7a
000000320cf36000      20 rw--- 0000000000036000 008:00003 libssl.so.0.9.7a
000000320cf3b000       4 rw--- 000000320cf3b000 000:00000   [ anon ]
0000007fbffa7000     356 rw--- 0000007fbffa7000 000:00000   [ stack ]
ffffffffff600000    8192 ----- 0000000000000000 000:00000   [ anon ]
mapped: 147272K    writeable/private: 98744K    shared: 0K

Resident Size

The Resident Size (RES in 'top' output) for the process with PID 7659 is 99MB. This is the net amount amount of memory consumed by the process.

The app

Whoa, that's a lot of memory! rake:stats ...


(in /Users/lourens/projects/bookings)
+----------------------+-------+-------+---------+---------+-----+-------+
| Name                 | Lines |   LOC | Classes | Methods | M/C | LOC/M |
+----------------------+-------+-------+---------+---------+-----+-------+
| Controllers          |  5622 |  4351 |      99 |     604 |   6 |     5 |
| Helpers              |  2493 |  1909 |       0 |     467 |   0 |     2 |
| Models               |  5654 |  4067 |     209 |     685 |   3 |     3 |
| Libraries            |  2258 |  1476 |      42 |     210 |   5 |     5 |
| APIs                 |     0 |     0 |       0 |       0 |   0 |     0 |
| Components           |     0 |     0 |       0 |       0 |   0 |     0 |
| Model specs          | 14977 | 11275 |       0 |     131 |   0 |    84 |
| View specs           |     0 |     0 |       0 |       0 |   0 |     0 |
| Controller specs     | 24538 | 18954 |       0 |       0 |   0 |     0 |
| Helper specs         |     0 |     0 |       0 |       0 |   0 |     0 |
+----------------------+-------+-------+---------+---------+-----+-------+
| Total                | 55542 | 42032 |     350 |    2097 |   5 |    18 |
+----------------------+-------+-------+---------+---------+-----+-------+
  Code LOC: 11803     Test LOC: 30229     Code to Test Ratio: 1:2.6

Memcached is used extensively.

My memory hogs

In addition to application code and stock Rails:

  • PDF Writer and TZinfo gems
  • Globalize ( 8 languages, 1400 translations per language, preloaded in config.after_initialize ) and another 20 odd plugins
  • Per request local cache for cache_fu

Memory usage for remainder of the stack

Nginx, neglible:


[root@somehost bookings]# ps aux | grep nginx
root     17280  0.0  0.0 18192  548 ?        Ss   Apr22   0:00 nginx: master process /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
nginx    17281  0.0  0.1 18948 2400 ?        S    Apr22  13:12 nginx: worker process                                          
nginx    17282  0.0  0.1 18828 2196 ?        S    Apr22  12:58 nginx: worker process                                          

Mysql, pretty standard:


[root@somehost bookings]# ps aux | grep mysql
root     10187  0.0  0.0 53840 1316 ?        S    May03   0:00 /bin/sh /usr/bin/mysqld_safe --datadir=/mysql/data --pid-file=/mysql/data/somehost.com.pid
mysql    10226  0.1  3.5 733792 73524 ?      Sl   May03  18:24 /usr/sbin/mysqld --basedir=/ --datadir=/mysql/data --user=mysql --pid-file=/mysql/data/somehost.com.pid --skip-external-locking --port=3306 --socket=/var/lib/mysql/mysql.sock

PHP:


[root@somehost bookings]# ps aux | grep php
505       8352  0.0  0.0 58880 1172 ?        Ss   Mar28   0:00 /usr/local/bin/php
505       7597  0.8  0.6 71172 14304 ?       S    11:29   0:23 /usr/local/bin/php
505       7750  0.9  0.6 71160 14276 ?       S    11:54   0:13 /usr/local/bin/php
505       7754  0.9  0.6 71232 14272 ?       S    11:55   0:11 /usr/local/bin/php
505       7820  1.1  0.4 65284 8436 ?        S    12:06   0:07 /usr/local/bin/php
505       7823  1.0  0.6 71232 14288 ?       S    12:08   0:04 /usr/local/bin/php

Memcached:


[root@somehost bookings]# ps aux | grep memcached
502       5354  0.0  1.3 45784 28320 ?       Ss   May04   0:13 memcached -d -m 128 -p 11211 -u memcached

After a decent warmup

Snapshot of the Mongrels - 4000 requests (concurrency 8, 250 calls, rate of 2) across the Nginx/MySQL/Mongrel stack :


[root@somehost bookings]# ps aux | grep mongrel
mongrel   7659  0.7  5.8 164704 120156 ?     S    11:35   1:20 /usr/local/bin/ruby /usr/local/bin/mongrel_rails start -d -e production -p 8000 -a 127.0.0.1 -P /u/apps/bookings/current/log/mongrel.8000.pid -c /u/apps/bookings/current --user mongrel --group mongrel
mongrel   7662  0.7  5.8 164668 120128 ?     S    11:35   1:20 /usr/local/bin/ruby /usr/local/bin/mongrel_rails start -d -e production -p 8001 -a 127.0.0.1 -P /u/apps/bookings/current/log/mongrel.8001.pid -c /u/apps/bookings/current --user mongrel --group mongrel
mongrel   7665  0.7  5.8 164728 120180 ?     S    11:35   1:20 /usr/local/bin/ruby /usr/local/bin/mongrel_rails start -d -e production -p 8002 -a 127.0.0.1 -P /u/apps/bookings/current/log/mongrel.8002.pid -c /u/apps/bookings/current --user mongrel --group mongrel
mongrel   7668  0.8  5.8 165300 120668 ?     S    11:35   1:21 /usr/local/bin/ruby /usr/local/bin/mongrel_rails start -d -e production -p 8003 -a 127.0.0.1 -P /u/apps/bookings/current/log/mongrel.8003.pid -c /u/apps/bookings/current --user mongrel --group mongrel
mongrel   7671  0.8  5.8 164636 120084 ?     S    11:35   1:20 /usr/local/bin/ruby /usr/local/bin/mongrel_rails start -d -e production -p 8004 -a 127.0.0.1 -P /u/apps/bookings/current/log/mongrel.8004.pid -c /u/apps/bookings/current --user mongrel --group mongrel
mongrel   7674  0.8  5.8 164988 120400 ?     S    11:35   1:20 /usr/local/bin/ruby /usr/local/bin/mongrel_rails start -d -e production -p 8005 -a 127.0.0.1 -P /u/apps/bookings/current/log/mongrel.8005.pid -c /u/apps/bookings/current --user mongrel --group mongrel
mongrel   7677  0.7  5.8 164772 120224 ?     S    11:35   1:20 /usr/local/bin/ruby /usr/local/bin/mongrel_rails start -d -e production -p 8006 -a 127.0.0.1 -P /u/apps/bookings/current/log/mongrel.8006.pid -c /u/apps/bookings/current --user mongrel --group mongrel
mongrel   7680  0.8  5.8 164840 120188 ?     S    11:36   1:20 /usr/local/bin/ruby /usr/local/bin/mongrel_rails start -d -e production -p 8007 -a 127.0.0.1 -P /u/apps/bookings/current/log/mongrel.8007.pid -c /u/apps/bookings/current --user mongrel --group mongrel

Resident Size increased by 20MB to 24MB per process.

Why memory increases after warm up

  • Any gems or libs referenced by your plugins, environment files and config.after_initialize blocks will be required on process startup.
  • The Dependencies mechanism in Rails >= 1.2 kicks in after the first request, during which most of your application code and gems/libs not required during initialization is loaded.
  • String count in ObjectSpace will increase dramaticly: ERB templates/partials, routes, lib/file paths, generated SQL and Marshalled data if you're using a cache backend.

Your process size after proper warmup should remain more or less constant (give or take for GC).

What to do if you suspect memory leaks

Bleak House

An excellent tool for polling your production environment at set intervals.A pure C (custom binary) and ObjectSpace version is available.

Mongrel "Dash-Bee" logging

Start Mongrel with the '-B' switch. This yields a few log files in RAILSROOT/log/mongreldebug, of which you should inspect the following :

  • objects.log - A log of all the Objects currently in ObjectSpace.Diff this per request count and watch for a growing Delta.
  • files.log - Lists open file descriptors.Useful if your application is IO bound.

Finding open file descriptors

'lsof' is a neat utility for listing open ports, sockets and files on a per process basis.


[root@somehost bookings]# /usr/sbin/lsof -p 7659
COMMAND    PID    USER   FD   TYPE             DEVICE     SIZE     NODE NAME
mongrel_r 7659 mongrel  cwd    DIR                8,3     4096  1639306 /u/apps/bookings/releases/20070510100305
mongrel_r 7659 mongrel  rtd    DIR                8,3     4096        2 /
mongrel_r 7659 mongrel  txt    REG                8,3  2493404  1696180 /usr/local/bin/ruby
mongrel_r 7659 mongrel  mem    REG                8,3    32267  1926292 /usr/local/lib/ruby/1.8/x86_64-linux/digest.so
mongrel_r 7659 mongrel  mem    REG                8,3   832033  1926293 /usr/local/lib/ruby/1.8/x86_64-linux/openssl.so
mongrel_r 7659 mongrel  mem    REG                8,3    10544  1926290 /usr/local/lib/ruby/1.8/x86_64-linux/fcntl.so
mongrel_r 7659 mongrel  mem    REG                8,3    51414  1926305 /usr/local/lib/ruby/1.8/x86_64-linux/stringio.so
mongrel_r 7659 mongrel  mem    REG                8,3   341425  1926303 /usr/local/lib/ruby/1.8/x86_64-linux/syck.so
mongrel_r 7659 mongrel  mem    REG                8,3   119273  1926301 /usr/local/lib/ruby/1.8/x86_64-linux/socket.so
mongrel_r 7659 mongrel  mem    REG                8,3    74815  2330154 /usr/local/lib/ruby/gems/1.8/gems/mongrel-1.0.1/lib/http11.so
mongrel_r 7659 mongrel  mem    REG                8,3    46134  1920694 /usr/local/lib/ruby/gems/1.8/gems/fastthread-1.0/lib/fastthread.so
mongrel_r 7659 mongrel  mem    REG                8,3    45517  1926304 /usr/local/lib/ruby/1.8/x86_64-linux/thread.so
mongrel_r 7659 mongrel  mem    REG                8,3   108943  1926307 /usr/local/lib/ruby/1.8/x86_64-linux/zlib.so
mongrel_r 7659 mongrel  mem    REG                8,3    24565  1926302 /usr/local/lib/ruby/1.8/x86_64-linux/etc.so
mongrel_r 7659 mongrel  mem    REG                8,3    56902  2588702 /lib64/libnss_files-2.3.4.so
mongrel_r 7659 mongrel  mem    REG                8,3    47492  1926298 /usr/local/lib/ruby/1.8/x86_64-linux/strscan.so
mongrel_r 7659 mongrel  mem    REG                8,3   424522  1926299 /usr/local/lib/ruby/1.8/x86_64-linux/nkf.so
mongrel_r 7659 mongrel  mem    REG                8,3   131340  1926308 /usr/local/lib/ruby/1.8/x86_64-linux/bigdecimal.so
mongrel_r 7659 mongrel  mem    REG                8,3    12623  1926296 /usr/local/lib/ruby/1.8/x86_64-linux/digest/md5.so
mongrel_r 7659 mongrel  mem    REG                8,3    37234  1926306 /usr/local/lib/ruby/1.8/x86_64-linux/racc/cparse.so
mongrel_r 7659 mongrel  mem    REG                8,3    40134  1926291 /usr/local/lib/ruby/1.8/x86_64-linux/iconv.so
mongrel_r 7659 mongrel  mem    REG                8,3    13615  1926295 /usr/local/lib/ruby/1.8/x86_64-linux/digest/sha1.so
mongrel_r 7659 mongrel  mem    REG                8,3  4756583  1920155 /usr/local/lib/ruby/site_ruby/1.8/x86_64-linux/mysql.so
mongrel_r 7659 mongrel  mem    REG                8,3    21546  1721087 /usr/lib64/gconv/gconv-modules.cache
mongrel_r 7659 mongrel  mem    REG                8,3    24492   359548 /home/mongrel/.ruby_inline/Inline_ImageScience_aa58.so
mongrel_r 7659 mongrel  mem    REG                8,3  1547144  1697450 /usr/lib/libfreeimage-3.9.3.so
mongrel_r 7659 mongrel  mem    REG                8,3    47496  2588909 /lib64/libgcc_s-3.4.6-20060404.so.1
mongrel_r 7659 mongrel  mem    REG                8,3   105080  2588770 /lib64/ld-2.3.4.so
mongrel_r 7659 mongrel  mem    REG                8,3  1493409  2588771 /lib64/tls/libc-2.3.4.so
mongrel_r 7659 mongrel  mem    REG                8,3    17943  2588904 /lib64/libdl-2.3.4.so
mongrel_r 7659 mongrel  mem    REG                8,3   613297  2588908 /lib64/tls/libm-2.3.4.so
mongrel_r 7659 mongrel  mem    REG                8,3    79336  1701661 /usr/lib64/libz.so.1.2.1.2
mongrel_r 7659 mongrel  mem    REG                8,3    91412  2588903 /lib64/libresolv-2.3.4.so
mongrel_r 7659 mongrel  mem    REG                8,3    30070  2588910 /lib64/libcrypt-2.3.4.so
mongrel_r 7659 mongrel  mem    REG                8,3   107187  2588726 /lib64/libnsl-2.3.4.so
mongrel_r 7659 mongrel  mem    REG                8,3    10384  2588902 /lib64/libcom_err.so.2.1
mongrel_r 7659 mongrel  mem    REG                8,3   464040  1701659 /usr/lib64/libkrb5.so.3.2
mongrel_r 7659 mongrel  mem    REG                8,3  1230232  2588905 /lib64/libcrypto.so.0.9.7a
mongrel_r 7659 mongrel  mem    REG                8,3   145456  1698080 /usr/lib64/libk5crypto.so.3.0
mongrel_r 7659 mongrel  mem    REG                8,3    93832  1701660 /usr/lib64/libgssapi_krb5.so.2.2
mongrel_r 7659 mongrel  mem    REG                8,3   910744  1697214 /usr/lib64/libstdc++.so.6.0.3
mongrel_r 7659 mongrel  mem    REG                8,3   244320  2588906 /lib64/libssl.so.0.9.7a
mongrel_r 7659 mongrel    0r   CHR                1,3              1982 /dev/null
mongrel_r 7659 mongrel    1w   REG                8,3   572768  1579794 /u/apps/bookings/shared/log/mongrel.log
mongrel_r 7659 mongrel    2w   REG                8,3   572768  1579794 /u/apps/bookings/shared/log/mongrel.log
mongrel_r 7659 mongrel    3u  IPv4           14667600               TCP localhost.localdomain:8000 (LISTEN)
mongrel_r 7659 mongrel    4w   REG                8,3 68750821  1579790 /u/apps/bookings/shared/log/production.log
mongrel_r 7659 mongrel    5u  IPv4           14667733               TCP localhost.localdomain:39863->localhost.localdomain:11211 (ESTABLISHED)
mongrel_r 7659 mongrel    6u  unix 0x0000010072f89380          14690356 socket
mongrel_r 7659 mongrel    7w   REG                8,3       57  1556510 /u/apps/bookings/shared/log/memory.log
mongrel_r 7659 mongrel    9r   DIR                8,3     4096  1823783 /u/apps/bookings/releases/20070510100305/public/stylesheets
mongrel_r 7659 mongrel   10r   DIR                8,3     4096  1823783 /u/apps/bookings/releases/20070510100305/public/stylesheets
mongrel_r 7659 mongrel   11r   DIR                8,3     4096  1823783 /u/apps/bookings/releases/20070510100305/public/stylesheets
mongrel_r 7659 mongrel   12r   DIR                8,3     4096  1823783 /u/apps/bookings/releases/20070510100305/public/stylesheets
mongrel_r 7659 mongrel   13r   DIR                8,3     4096  1823783 /u/apps/bookings/releases/20070510100305/public/stylesheets
mongrel_r 7659 mongrel   14r   DIR                8,3     4096  1823783 /u/apps/bookings/releases/20070510100305/public/stylesheets
mongrel_r 7659 mongrel   15r   DIR                8,3     4096  1823783 /u/apps/bookings/releases/20070510100305/public/stylesheets
mongrel_r 7659 mongrel   16r   DIR                8,3     4096  1823783 /u/apps/bookings/releases/20070510100305/public/stylesheets
mongrel_r 7659 mongrel   17r   DIR                8,3     4096  1823783 /u/apps/bookings/releases/20070510100305/public/stylesheets
mongrel_r 7659 mongrel   18r   DIR                8,3     4096  1823783 /u/apps/bookings/releases/20070510100305/public/stylesheets
mongrel_r 7659 mongrel   19r   DIR                8,3     4096  1823783 /u/apps/bookings/releases/20070510100305/public/stylesheets
mongrel_r 7659 mongrel   20r   DIR                8,3     4096  1823783 /u/apps/bookings/releases/20070510100305/public/stylesheets
mongrel_r 7659 mongrel   21r   DIR                8,3     4096  1823783 /u/apps/bookings/releases/20070510100305/public/stylesheets
mongrel_r 7659 mongrel   22r   DIR                8,3     4096  1823783 /u/apps/bookings/releases/20070510100305/public/stylesheets
mongrel_r 7659 mongrel   23r   DIR                8,3     4096  1823783 /u/apps/bookings/releases/20070510100305/public/stylesheets
mongrel_r 7659 mongrel   24r   DIR                8,3     4096  1823783 /u/apps/bookings/releases/20070510100305/public/stylesheets
mongrel_r 7659 mongrel   25r   DIR                8,3     4096  2528355 /u/apps/bookings/releases/20070510100305/public/javascripts
mongrel_r 7659 mongrel   26r   DIR                8,3     4096  2528355 /u/apps/bookings/releases/20070510100305/public/javascripts
mongrel_r 7659 mongrel   27r   DIR                8,3     4096  2528355 /u/apps/bookings/releases/20070510100305/public/javascripts
mongrel_r 7659 mongrel   28r   DIR                8,3     4096  2528355 /u/apps/bookings/releases/20070510100305/public/javascripts
mongrel_r 7659 mongrel   29r   DIR                8,3     4096  2528355 /u/apps/bookings/releases/20070510100305/public/javascripts
mongrel_r 7659 mongrel   30r   DIR                8,3     4096  2528355 /u/apps/bookings/releases/20070510100305/public/javascripts
mongrel_r 7659 mongrel   31r   DIR                8,3     4096  2528355 /u/apps/bookings/releases/20070510100305/public/javascripts
mongrel_r 7659 mongrel   32r   DIR                8,3     4096  2528355 /u/apps/bookings/releases/20070510100305/public/javascripts
mongrel_r 7659 mongrel   33r   DIR                8,3     4096  2528355 /u/apps/bookings/releases/20070510100305/public/javascripts
mongrel_r 7659 mongrel   34r   DIR                8,3     4096  2528355 /u/apps/bookings/releases/20070510100305/public/javascripts
mongrel_r 7659 mongrel   35r   DIR                8,3     4096  2528355 /u/apps/bookings/releases/20070510100305/public/javascripts
mongrel_r 7659 mongrel   36r   DIR                8,3     4096  2528355 /u/apps/bookings/releases/20070510100305/public/javascripts
mongrel_r 7659 mongrel   37r   DIR                8,3     4096  2528355 /u/apps/bookings/releases/20070510100305/public/javascripts
mongrel_r 7659 mongrel   38r   DIR                8,3     4096  2528355 /u/apps/bookings/releases/20070510100305/public/javascripts
mongrel_r 7659 mongrel   39r   DIR                8,3     4096  2528355 /u/apps/bookings/releases/20070510100305/public/javascripts
mongrel_r 7659 mongrel   40r   DIR                8,3     4096  1823783 /u/apps/bookings/releases/20070510100305/public/stylesheets
mongrel_r 7659 mongrel   41r   DIR                8,3     4096  1823783 /u/apps/bookings/releases/20070510100305/public/stylesheets
mongrel_r 7659 mongrel   42r   DIR                8,3     4096  1823783 /u/apps/bookings/releases/20070510100305/public/stylesheets
mongrel_r 7659 mongrel   43r   DIR                8,3     4096  1823783 /u/apps/bookings/releases/20070510100305/public/stylesheets
mongrel_r 7659 mongrel   44r   DIR                8,3     4096  1823783 /u/apps/bookings/releases/20070510100305/public/stylesheets
mongrel_r 7659 mongrel   45r   DIR                8,3     4096  1823783 /u/apps/bookings/releases/20070510100305/public/stylesheets
mongrel_r 7659 mongrel   46r   DIR                8,3     4096  1823783 /u/apps/bookings/releases/20070510100305/public/stylesheets
mongrel_r 7659 mongrel   47r   DIR                8,3     4096  1823783 /u/apps/bookings/releases/20070510100305/public/stylesheets
mongrel_r 7659 mongrel   48r   DIR                8,3     4096  1823783 /u/apps/bookings/releases/20070510100305/public/stylesheets
mongrel_r 7659 mongrel   49r   DIR                8,3     4096  1823783 /u/apps/bookings/releases/20070510100305/public/stylesheets
mongrel_r 7659 mongrel   50r   DIR                8,3     4096  1823783 /u/apps/bookings/releases/20070510100305/public/stylesheets
mongrel_r 7659 mongrel   51r   DIR                8,3     4096  1823783 /u/apps/bookings/releases/20070510100305/public/stylesheets
mongrel_r 7659 mongrel   52r   DIR                8,3     4096  1823783 /u/apps/bookings/releases/20070510100305/public/stylesheets
mongrel_r 7659 mongrel   53r   DIR                8,3     4096  1823783 /u/apps/bookings/releases/20070510100305/public/stylesheets
mongrel_r 7659 mongrel   54r   DIR                8,3     4096  1823783 /u/apps/bookings/releases/20070510100305/public/stylesheets
mongrel_r 7659 mongrel   55r   DIR                8,3     4096  1823783 /u/apps/bookings/releases/20070510100305/public/stylesheets
mongrel_r 7659 mongrel   56r   DIR                8,3     4096  2528355 /u/apps/bookings/releases/20070510100305/public/javascripts
mongrel_r 7659 mongrel   57r   DIR                8,3     4096  2528355 /u/apps/bookings/releases/20070510100305/public/javascripts
mongrel_r 7659 mongrel   58r   DIR                8,3     4096  2528355 /u/apps/bookings/releases/20070510100305/public/javascripts
mongrel_r 7659 mongrel   59r   DIR                8,3     4096  2528355 /u/apps/bookings/releases/20070510100305/public/javascripts
mongrel_r 7659 mongrel   60r   DIR                8,3     4096  2528355 /u/apps/bookings/releases/20070510100305/public/javascripts
mongrel_r 7659 mongrel   61r   DIR                8,3     4096  2528355 /u/apps/bookings/releases/20070510100305/public/javascripts
mongrel_r 7659 mongrel   62r   DIR                8,3     4096  2528355 /u/apps/bookings/releases/20070510100305/public/javascripts
mongrel_r 7659 mongrel   63r   DIR                8,3     4096  2528355 /u/apps/bookings/releases/20070510100305/public/javascripts
mongrel_r 7659 mongrel   64r   DIR                8,3     4096  2528355 /u/apps/bookings/releases/20070510100305/public/javascripts
mongrel_r 7659 mongrel   65r   DIR                8,3     4096  2528355 /u/apps/bookings/releases/20070510100305/public/javascripts
mongrel_r 7659 mongrel   66r   DIR                8,3     4096  2528355 /u/apps/bookings/releases/20070510100305/public/javascripts
mongrel_r 7659 mongrel   67r   DIR                8,3     4096  2528355 /u/apps/bookings/releases/20070510100305/public/javascripts
mongrel_r 7659 mongrel   68r   DIR                8,3     4096  2528355 /u/apps/bookings/releases/20070510100305/public/javascripts
mongrel_r 7659 mongrel   69r   DIR                8,3     4096  2528355 /u/apps/bookings/releases/20070510100305/public/javascripts
mongrel_r 7659 mongrel   70r   DIR                8,3     4096  2528355 /u/apps/bookings/releases/20070510100305/public/javascripts

MemoryProfiler

Scott Laird and Ryan Davis hacked up a memory leak spotter with a very useful strings logger. Rails plugin available here.

WeakRef

The WeakRef Standard Library class can be used to clean up in tough spots where the GC doesn't clean up properly.In process caches etc. See WeakHash for in depth usage.

Custom logging

I use the following pattern ( credits to BleakHouse ) for logging without polluting the application with ActionController filters:

class Dispatcher
  class << self
    def reset_after_dispatch_with_globalize
      translator = Globalize::DbViewTranslator.instance     
      ActiveRecord::Base.logger.info "Cache size: #{translator.cache_size}, Cache total hits: #{translator.cache_total_hits}, Cache total queries: #{translator.cache_total_queries}, Cache keys total: #{translator.instance_variable_get(:@cache).keys.size}"
      reset_after_dispatch() 
    end
    alias_method_chain :reset_after_dispatch, :globalize

  end
 end

Conclusion

Rails is greedy on Memory, however :

  • If you spent the time developing and testing an application, why cut back on resources if a Dual Core box with 2GB RAM can be rented for $130 to $200 p/m at many respectable hosts?

  • Many opt for VPS solutions, which pretty much require at least some sysadmin skills ... is the time and monitoring spent on avoiding swap space for anything more than a blog really worth it?

  • I like the Container/Slice approach offered by Joyent and Engine Yard a lot from a administration and management perspective, but can't help feeling restricted by the memory offered ( Memcached? ).Adding an additional 1GB to a dedicated box will cost you $15 to $30 at most providers ... but in Container/Slice terms that's an additional container, worst case scenario.

  • I assume many large Rails applications have a Resident Size of 100MB to 130MB per process average, anyone care to chime in and share some production memory usage for others to have a baseline before loosing sleep over memory consumption?


About this entry