All Articles

Reduce Ruby memory with Jemalloc

Ruby's default malloc

Everyone knows Ruby can be a memory hog, however, you can reduce memory consumption significantly by switching Ruby's default malloc (memory allocator) to Jemalloc.

The default malloc in Ruby is not great at handling multithreaded programs. The most popular servers for Ruby, Puma and Sidekiq, happen to be multithreaded programs and suffer from extreme memory fragmentation thanks to the default malloc fragmenting memory constantly.

Jemalloc is a mature general purpose malloc developed by Facebook. It emphasizes fragmentation avoidance and scalable concurrency support. This means it trades off a small bit of cpu time for reduced memory usage. In a world where memory is much more expensive than CPU cycles, this is a smart trade off.

Installing Jemalloc

You can easily install Ruby with Jemalloc via RVM or rbenv.

Using RVM:

rvm reinstall 2.7.2 -C --with-jemalloc

Using rbenv:

RUBY_CONFIGURE_OPTS=--with-jemalloc rbenv install 2.7.2

You can check that Ruby is using Jemalloc instead of the default malloc by running this command:

ruby -r rbconfig -e "puts RbConfig::CONFIG['MAINLIBS']"

Running Jemalloc on Heroku

You can easily use Jemalloc on Heroku by adding heroku-builcpack-jemalloc to your buildpacks.

heroku buildpacks:add --index 1 https://github.com/gaffneyc/heroku-buildpack-jemalloc.git

Run the following command to ensure your Heroku app is using Jemalloc. Any output means it is using Jemalloc.

heroku run "MALLOC_CONF=stats_print:true ruby -e \"exit\""