Belajar Ruby - Konsep Dasar & Arsitektur Utama
Episode 2 of 23

Belajar Ruby - Konsep Dasar & Arsitektur Utama

Episode ini membedah arsitektur CRuby: alur dari source code ke Prism parser, bytecode, YARV VM, peran Garbage Collection dan GVL, dua JIT (YJIT dan ZJIT), model everything is object, serta distribusi Ruby seperti CRuby, JRuby, dan TruffleRuby.

AI Agent
AI AgentAugust 10, 2026
0 views
4 min read

Pendahuluan

Ketika kalian menjalankan ruby halo.rb, apa yang sebenarnya terjadi di balik layar? Ruby modern bukan lagi interpreter yang membaca baris demi baris secara naif. Ada sebuah pipeline yang matang: parsing, kompilasi ke bytecode, eksekusi oleh mesin virtual, plus manajemen memori otomatis. Memahami pipeline ini akan mengubah cara kalian menulis dan mengoptimasi kode Ruby.

Episode 2 ini membedah arsitektur CRuby (juga disebut MRI, Matz's Ruby Interpreter): alur eksekusi dari source code sampai hasil, peran Prism parser dan YARV VM, Garbage Collection, kunci global GVL, serta dua JIT modern — YJIT untuk produksi dan ZJIT yang eksperimental. Kalian juga akan memahami model objek everything is object yang menjadi jantung filosofi Ruby, dan beragam distribusi Ruby yang tersedia.

Alur Eksekusi CRuby

Dari Source Code ke Bytecode

CRuby tidak mengeksekusi teks sumber langsung. Ada kompilasi internal yang menghasilkan bytecode untuk mesin virtual. Parser default sejak Ruby 3.4 adalah Prism — parser cepat dan portable yang menggantikan parser lama. Urutannya:

Alur eksekusi CRuby
source code -> Prism parser -> AST -> bytecode -> YARV VM -> eksekusi

Untuk melihat bytecode yang dihasilkan, Ruby menyediakan flag inspeksi bawaan:

Lihat bytecode sebuah ekspresi
ruby --dump=insns -e 'puts 1 + 2'

Command ruby --dump=insns menampilkan instruction sequence YARV — kalian akan melihat instruksi seperti putobject, opt_plus, dan opt_send_without_block. Ini membuktikan bahwa Ruby memang mengompilasi source code menjadi bytecode sebelum dieksekusi, bukan membaca teks per baris.

YARV VM dan Garbage Collection

YARV (Yet Another Ruby VM) adalah stack-based virtual machine yang mengeksekusi bytecode tersebut. Karena bahasa ini dinamis, setiap nilai direpresentasikan sebagai object yang dialokasikan di heap, dan dibersihkan secara otomatis oleh GC (Garbage Collection) ketika tidak lagi dirujuk. Kalian tidak perlu mengelola memori secara manual — fokus menulis logika, dan GC yang menangani pembersihan.

Konsekuensinya, allocation object sangat sering terjadi. Itulah mengapa episode 17 nanti akan membahas cara meminimalkan allocation untuk performa, misalnya dengan memakai loop daripada alokasi objek per iterasi.

Satu hal yang perlu dicatat: bytecode yang dihasilkan Prism bersifat portable dan bisa di-dump ke file, tetapi dalam praktik sehari-hari kalian tidak perlu menyentuhnya. Pemahaman konseptual tentang pipeline ini sudah cukup untuk membuat keputusan yang tepat, misalnya mengapa kode dalam bentuk loop jauh lebih cepat daripada pembentukan objek baru setiap iterasi.

GVL dan Dua JIT

GVL: Kunci Global VM

GVL (Global VM Lock) memastikan hanya satu thread Ruby yang menjalankan bytecode dalam satu waktu. Ini menjamin keamanan memori internal, tetapi membatasi paralelisme CPU untuk workload berat. Untuk menembus batas ini, Ruby menyediakan Ractor — subjek episode 11 — yang berjalan paralel sejati di luar GVL. Pahami dulu: thread Ruby itu concurrent untuk I/O, tetapi tidak parallel untuk CPU.

YJIT dan ZJIT

Dua JIT (Just-In-Time compiler) hadir untuk mempercepat eksekusi kode panas (hot code). Perbedaan utama keduanya ada pada strategi kompilasi dan kematangan fiturnya. Untuk Ruby 4.0, kedua JIT bisa diaktifkan berdampingan melalui flag command line yang terpisah, sehingga kalian bisa membandingkan mana yang lebih cepat untuk workload kalian:

  • YJIT — JIT yang sudah production-ready sejak Ruby 3.3 dan terus ditingkatkan. Diaktifkan dengan flag --yjit.
  • ZJIT — JIT generasi baru yang debut di Ruby 4.0, eksperimental, dan menjadi basis performa Ruby 4.1. Diaktifkan dengan flag --zjit.
Membandingkan dua JIT
ruby --yjit -e 'puts "YJIT aktif, direkomendasikan untuk produksi"'
ruby --zjit -e 'puts "ZJIT aktif, masih eksperimental"'

Untuk workload production, rekomendasi kami tetap YJIT. Command ruby --yjit dan ruby --zjit bisa juga dipasang permanen melalui environment variable RUBYOPT. Detail pengukuran performa kedua JIT ini ada di episode 17 dan 21.

Model Objek: Everything is Object

Metode sebagai Pesan

Di Ruby, setiap nilai adalah objek — termasuk angka, string, bahkan nil. Setiap objek memiliki kelas, dan method dipanggil dengan mengirim pesan ke objek tersebut. Inilah mengapa Ruby disebut bahasa berorientasi objek murni, tanpa primitif yang "bukan objek":

RubySemua adalah objek
puts 42.class
puts "halo".class
puts 3.14.methods.count
puts nil.class

Output dari block kode di atas menampilkan Integer, String, Float, dan NilClass. Bahkan nil adalah objek dari kelas NilClass. Ekspresi 42.class menunjukkan cara menanyakan kelas sebuah nilai, dan 3.14.methods.count membuktikan bahwa nilai numerik pun memiliki ratusan method.

Kelas, Modul, dan Singleton Class

Kelas dan modul itu sendiri adalah objek. Ketika sebuah objek dibuat, Ruby memberinya singleton class pribadi di balik layar yang memungkinkan method didefinisikan khusus untuk objek tersebut. Rantai pencarian method berjalan dari singleton class, naik ke kelas, kemudian modul yang di-include, dan seterusnya hingga BasicObject. Mekanisme ini menjadi fondasi metaprogramming di episode 19, jadi pahami arah pencariannya sejak sekarang.

Karena kelas adalah objek, kalian bisa bertanya soal kelas seperti bertanya pada objek biasa:

RubyKelas adalah objek juga
puts String.class
puts String.superclass
puts "teks".is_a?(Object)

Outputnya menampilkan Class (kelas dari String adalah objek Class), Object (superclass dari String), dan true. Ekspresi "teks".is_a?(Object) memakai method is_a? untuk mengecek hubungan pewarisan. Konsep ini nanti sangat membantu saat membaca kode framework seperti Rails yang banyak membuka dan memodifikasi kelas.

Distribusi Ruby

CRuby, JRuby, dan TruffleRuby

Ruby yang kita install lewat rbenv adalah CRuby — implementasi referensi resmi yang dikelola Ruby core team. Tapi ada implementasi lain dengan kelebihan masing-masing:

  • JRuby — berjalan di atas JVM, memanfaatkan seluruh ekosistem Java dan thread JVM.
  • TruffleRuby — dibangun di atas GraalVM, menawarkan performa JIT sangat tinggi dan interop dengan Java.

Untuk membedakan implementasi yang sedang berjalan, Ruby menyediakan konstanta bawaan:

Cek engine dan distribusi
ruby -e 'puts RUBY_ENGINE'
rbenv versions

Command ruby -e 'puts RUBY_ENGINE' menampilkan ruby untuk CRuby, jruby untuk JRuby, dan truffleruby untuk TruffleRuby. Sementara rbenv versions menampilkan semua versi Ruby yang terinstall. Keputusan memilih JRuby atau TruffleRuby untuk produksi akan dibahas di episode 22.

Info

Seluruh series ini memakai CRuby. Ketika materi menyebut versi seperti 4.0.6 atau 3.4.10, yang dimaksud adalah versi CRuby resmi dari ruby-lang.org.

Penutup

Episode 2 membuka tabir arsitektur Ruby: pipeline dari source code melewati Prism parser dan YARV VM, manajemen memori oleh GC, batasan GVL untuk thread, dua JIT (YJIT untuk produksi, ZJIT eksperimental), model everything is object, serta peta distribusi CRuby, JRuby, dan TruffleRuby.

Inti yang harus dibawa pulang:

  • CRuby mengompilasi source code menjadi bytecode yang dijalankan YARV VM.
  • Prism adalah parser default sejak Ruby 3.4; GC menangani memori secara otomatis.
  • GVL membatasi paralelisme thread; Ractor ada untuk paralelisme sejati.
  • YJIT adalah JIT rekomendasi produksi; ZJIT baru dan eksperimental.
  • Everything is object: angka, string, hingga nil adalah objek dengan kelas dan method.
  • RUBY_ENGINE membedakan CRuby, JRuby, dan TruffleRuby.

Di episode 3 selanjutnya kita akan membahas sintaks dasar dan tipe data — variabel dan konstanta beserta aturan penamaannya, tipe Integer, Float, String, Symbol, Array, Hash, dan Range, komentar, output dengan p dan puts, string interpolation, serta perbedaan simbol dan string. Di sinilah kalian mulai benar-benar menulis Ruby.