Menurunkan penggunaan memory untuk aplikasi Ruby (newbie friendly)
Tags: ruby
Published: 2019-12-23 08:10:12

Bahasa Ruby merupakan salah satu bahasa yang memerlukan memory cukup besar. Hal ini berimbas pada kebutuhan memory yang besar di server, terutama ketika semakin banyak traffic dan background process yang perlu ditangani oleh aplikasi berbasis Ruby.

Salah satu cara untuk menurunkan penggunaan memory adalah dengan mengganti memory allocation library. Ruby secara default menggunakan `malloc`. Sekarang kita ganti dengan `jemalloc`.

> Redis telah menggunakan `jemalloc` selama beberapa tahun. Berkat penggunaan `jemalloc`, Redis berhasil mengurangi penggunaan memory ketika dijalankan.

Apakah penggunaan `jemalloc` benar-benar berhasil? Semua, saya ulangi, **semua** artikel yang saya temukan mengenai penggunaan jemalloc untuk Ruby belum memiliki imbas buruk. Semuanya mengabarkan penurunan penggunaan memory pada aplikasi berbasis Ruby yang telah dibangun.

Beberapa artikel bahkan menggunakan `jemalloc` pada aplikasi yang telah menangani jutaan request dalam satu hari. Semakin besar skala aplikasi, semakin terasa keuntungan dari penggunaan `jemalloc`.

> Disclaimer: Artikel saya ini tidak akan membahas mengenai hasil sebelum dan sesudah penggunaan `jemalloc`. Fokus saya hanya untuk bagaimana mengatur agar Ruby yang kita miliki dapat menggunakan `jemalloc`. Artikel-artikel benchmark penggunaan `jemalloc` saya sertakan di akhir artikel ini.

### Install Jemalloc
Pada Linux, kita harus install jemalloc terlebih dahulu:
```
$ sudo apt update
$ sudo apt install libjemalloc-dev
```
Pada macOS cara paling mudah instalasi jemalloc adalah menggunakan Homebrew:
```
$ brew install jemalloc
```
> Perhatian: Karena `jemalloc` adalah C library, maka hanya bisa digunakan untuk Ruby MRI.

### Install Ruby
Instalasi Ruby pun harus diulang. Jika menggunakan rbenv, maka lakukan install Ruby dengan cara:
```
$ RUBY_CONFIGURE_OPTS=--with-jemalloc rbenv install 2.5.3
```
Jika menggunakan rvm, maka bisa install dengan cara:
```
$ rvm install 2.5.3 -C --with-jemalloc
```
Jika sebelumnya sudah terinstall versi Ruby, maka yang dilakukan adalah reinstall, bukan install.

Setelahnya, cek apakah versi Ruby yang diinstall telah menggunakan `jemalloc`:
```
$ ruby -r rbconfig -e "puts RbConfig::CONFIG['LIBS']"
```
Respon yang didapat kurang lebih akan seperti ini:
```
-lpthread -ljemalloc -lgmp -ldl -lcrypt -lm
```
Jika sudah ada `-ljemalloc` berarti versi Ruby yang baru diinstall sudah menggunakan `jemalloc`.

Restart aplikasi yang sedang berjalan (termasuk sidekiq, jika menggunakan sidekiq) maka aplikasi Ruby yang kita gunakan sudah akan menggunakan `jemalloc` sebagai memory allocation library.
> Perhatian: Penurunan penggunaan memory pada aplikasi berskala kecil tidak akan signifikan.

### Bagaimana di Heroku?
```
$ heroku buildpacks: set heroku/ruby
$ heroku buildpacks:add --index 1 https://github.com/scryfall/heroku-buildpack-jemalloc.git
$ git push heroku master
```
### Bagaimana benchmark penggunaan memory?
1. https://medium.com/@adrienjarthon/ruby-jemalloc-results-for-updown-io-d3fb2d32f67f
2. https://medium.com/rubyinside/how-we-halved-our-memory-consumption-in-rails-with-jemalloc-86afa4e54aa3
3. https://bubblin.io/blog/jemalloc