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?
2 comments
Jump to comment form | comments rss [?]