Ram optimizasyonu, malloc ve jemalloc

Selam,

Geliştirdiğimiz uygulamalar kullanılmaya başladıkça kapasite de yetmeyebiliyor.
Müşteriler tam sipariş verirken “Bu sepeti işlemeye RAM yetmeyecek yaa, artırmamız lazım” diyip, sunucuyu kapatamayız ya da sonsuza kadar yeni bir makine ekleyemeyiz.
Geliştirme maliyeti, parayı basıp yeni sunucu açma ya da kaynak ekleme maliyetinden yüksek olduğu sürece bunu savunmak biraz zor olabilir. Ama RAM problemleri sadece yeni bir müşterinin daha kullanabilmesinden öte, uygulamanın sıhhati için de bir sorun yaratabiliyor.
İş bu noktada, elimizdeki kaynakların suyunu çıkartmaya geliyor. (bkz. Etkinlik: Optimizing Resource Utilization for Ruby processes | Etkinlik kaydı eklendi! ) Tabi dilerseniz bu sorunu çözmek yerine yeni geliştirdiğim Aptherif diline geçerek saniyede 3 milyon isteğe cevap verebilirsiniz. (famous last words: en fazla n’olabilir ki?)

Eğer RAM ile alakalı sorunlar baş gösteriyorsa, genelde ilk önerilenlerden biri MALLOC_ARENA_MAX’ı 2 olarak tanımlamaktır. Yani, glibc’ kaç tane memory pool oluşturabileceğini kısıtlamak. Bu, worker’larda queue’ların görece yavaşlamasına neden olabilir, ama R14 almanızın büyük miktarda önüne geçecektir. Yetmez, ama evet.

Yakut’u takip ediyorsanız, akşam oturmalarını da dinleme fırsatı bulduysanız jemalloc’u kesin duymuşsunuzdur.

Jemalloc, adından anlaşılacağı gibi o da bir memory allocator. malloc’a göre ram’i daha verimli yönetiyor ve dillerden düşmüyor. Jemalloc kendisini şurada bahsetmiş: https://jemalloc.net/
Mike Perham da(Sidekiq’in(meşhur background job executor) maintainer’ı) bir şeyler demiş ve sonuna da bugs.ruby-lang.org’dan alıntılar eklemiş: Taming Rails memory bloat | Mike Perham

Jemalloc’la ilgili bir başka paylaşım:
https://twitter.com/sdogruyol/status/1536642810224513024

Eğer jemalloc kullanmayı düşünürseniz şu adımları takip edebilirsiniz:

Heroku kullanıyorsanız buildpack’inize gaffneyc/heroku-buildpack-jemalloc - Buildpacks - Heroku Elements
eklemeniz ve JEMALLOC_ENABLED’i true olarak env variable’lara eklemeniz yetecek. Nolur nolmaz diyerek de bilinen bir yerde durmakta fayda var. JEMALLOC_VERSION=5.2.1 eklemek de 5.2.1 versiyonunu kullanmamız sağlayacak.

Eğer sunucunuzu kendiniz yönetiyorsanız ya da container imajları kullanıyorsanız:

~$ JEMALLOC_VERSION=5.2.1 wget -O - https://github.com/jemalloc/jemalloc/releases/download/"${JEMALLOC_VERSION}"/jemalloc-"${JEMALLOC_VERSION}".tar.bz2 | tar -xj && \
    cd jemalloc-"${JEMALLOC_VERSION}" && \
    ./configure && \
    make && \
    make install

~$ cd && rm -rf jemalloc-"${JEMALLOC_VERSION}"

environment variable olarak da şunu eklemeyi atlamamak lazım:

LD_PRELOAD=“/app/vendor/jemalloc/lib/libjemalloc.so $LD_PRELOAD”

Şu şekilde de çalışıp çalışmadığını kontrol edebilirsiniz:

MALLOC_CONF=stats_print:true ruby -e "exit" 2>&1 | grep -o "jemalloc"

Sıcak sıcak tüketebilirsiniz, afiyet olsun. Dilerseniz buzluğa atıp, ihtiyacınız olduğunda çıkartıp çözünmesini beklemeden de kullanabilirsiniz.
Servis önerisi: Ruby versiyonunu 2.7.5’e çıkartmak, mümkünse 3’ü görmek damağınızı ve midenizi rahatlatır.

Peki, siz ne düşünüyorsunuz, sizin tercihiniz hangisi? Ne olur ne olmaz diyip, malloc’da kalıp MALLOC_ARENA_MAX mı kullanıyorsunuz? Yoksa, n’olabilir ki diyerek jemalloc mu kullanıyorsunuz?