This is a full write-up of my unsuccessful attempt today at adding Jemalloc to my Rails app on Heroku. I'd greatly appreciate any suggestions and am happy to answer questions and try stuff. One idea floating in my mind is to maybe try a different version of Jemalloc, ie. 3.6.0.
Background
My app is https://pullreminders.com and it uses Ruby 2.5.0, Rails 5.2.1, and Sidekiq. I run a single 2x Heroku dyno with 6 Puma workers using 5 threads each. This is on the heroku-18 stack. I was interested in jemalloc to see if I could reduce memory usage of my web server (so I could maybe run more Puma workers), scheduled jobs, and Sidekiq.
The steps I took to add jemalloc to my production app were:
- Enable Heroku Preboot to avoid downtime during dyno restarts
- Set env vars
JEMALLOC_ENABLED=true
and JEMALLOC_VERSION=5.0.1
- Add the buildpack with
heroku buildpacks:add --index 1 https://github.com/gaffneyc/heroku-buildpack-jemalloc.git
- Deploy an empty commit
git commit --allow-empty -m "empty commit"
I did this at at ~4:45 PST. Just mentioning this because it was after Heroku's incident that day was resolved.
Results
Almost immediately after adding jemalloc, I noticed an uptick in my app's response times. In the chart below, the bars represent response time, and the yellow line is throughput (which was low relative to earlier in the day).
I double checked my Heroku metrics which also showed an approximate doubling of both my 50th percentile and 95th percentile average response times. My mean response time had gone from ~150ms to ~300ms. My 95th percentile response times had gone from ~350ms to ~800ms and were a bit spikey. There were no timeouts or errors.
Memory usage appeared to be creeping back up to its pre-jemalloc level:
After a little while I removed jemalloc and deployed another empty commit to rebuild my app. Sure enough, response times fell back to their pre-jemalloc levels: