Bagaimana Program Mengakses RAM
1. RAM Fisik (Physical Memory)
RAM 8GB yang kamu lihat itu adalah memori fisik yang terpasang di motherboard. Ini adalah chip hardware yang menyimpan data dalam bentuk bit (0 dan 1).
Alamat fisik:
0x00000000
sampai0x1FFFFFFFF
(untuk 8GB)Setiap byte punya alamat unik
TAPI, program kamu TIDAK pernah akses RAM fisik secara langsung! Ini penting!
2. Virtual Memory (Memori Virtual)
Setiap program/proses mendapat ilusi bahwa mereka punya seluruh memori untuk diri mereka sendiri. Ini disebut virtual memory.
Kenapa perlu virtual memory?
Isolasi: Program A tidak bisa akses memori Program B (keamanan)
Simplifikasi: Program tidak perlu tahu di mana posisi fisik RAM-nya
Overcommitment: Total virtual memory semua program bisa lebih dari 8GB fisik
3. MMU (Memory Management Unit)
MMU adalah chip hardware (bagian dari CPU) yang mentranslasi alamat virtual ke alamat fisik.
Cara kerja:
Program: "Saya mau akses alamat 0x400000"
β
MMU: "OK, alamat virtual 0x400000 itu sebenarnya ada di RAM fisik 0x8A3F000"
β
RAM: Memberikan data dari alamat fisik tersebut
Page Table
MMU menggunakan Page Table (tabel halaman) untuk mapping:
Memori dibagi jadi chunk bernama pages (biasanya 4KB)
Page Table menyimpan mapping: Virtual Page β Physical Page
Disimpan di RAM, dikelola oleh OS kernel
4. Peran Kernel/OS
Kernel Linux/Windows adalah "manager" dari semua memori. Tugasnya:
a) Memory Allocation
Ketika program minta memori (malloc/new), kernel:
Cari physical page yang kosong
Update page table proses tersebut
Return alamat virtual ke program
b) Page Fault Handling
Kalau program akses alamat yang belum dimapping:
1. CPU: "Eh, page ini belum ada di page table!"
2. CPU: *trigger page fault exception*
3. Kernel: *terbangun*
4. Kernel: "OK, saya siapkan physical page-nya"
5. Kernel: "Update page table"
6. Kernel: "Lanjutkan program"
c) Memory Protection
Setiap page punya permission (read/write/execute). Kalau program coba akses yang tidak diizinkan β segmentation fault!
5. SWAP (Swap Space)
Ketika RAM fisik penuh, kernel bisa "mengusir" page yang jarang dipakai ke disk (swap).
Proses:
1. RAM penuh (8GB terpakai semua)
2. Program baru minta memory
3. Kernel: "Hmm, saya swap out page yang lama tidak dipakai"
4. Kernel: Copy page dari RAM ke disk (swap file/partition)
5. Kernel: Tandai page table bahwa page itu "swapped out"
6. Kernel: Berikan physical page yang dikosongkan ke program baru
Kalau program akses page yang di-swap:
1. CPU akses page β page fault
2. Kernel: "Oh, page ini di swap"
3. Kernel: Baca dari disk ke RAM (swap in)
4. Kernel: Mungkin swap out page lain kalau RAM masih penuh
5. Program lanjut
Swap itu LAMBAT karena disk jauh lebih lambat dari RAM (HDD: ~100 MB/s vs RAM: ~25 GB/s)
6. mmap (Memory Mapped Files)
mmap
adalah syscall yang "memetakan" file ke memory address space program.
Contoh:
// Buka file 1GB
file, _ := os.Open("bigdata.txt")
// mmap: peta file ke memory
data, _ := syscall.Mmap(int(file.Fd()), 0, size,
syscall.PROT_READ, syscall.MAP_SHARED)
// Akses seperti array biasa!
fmt.Println(data[1000]) // Baca byte ke-1000 dari file
Yang terjadi di belakang layar:
1. mmap() tidak langsung load 1GB ke RAM!
2. Hanya setup page table: "alamat virtual X = file offset Y"
3. Saat program akses data[1000] β page fault
4. Kernel: "Oh ini mmap-ed file, baca dari disk"
5. Kernel: Load 4KB (1 page) dari file ke RAM
6. Program lanjut
Keuntungan mmap:
Efficient: hanya load yang diakses
Shared memory: beberapa proses bisa mmap file yang sama
OS bisa cache-kan di page cache
7. Go Runtime Memory Management
Go punya memory allocator sendiri di atas syscall OS:
a) Memory Arena
Go runtime minta memory dari OS dalam chunk besar (biasanya beberapa MB):
Go Runtime: "Hey OS, kasih saya 64MB" β OS: berikan virtual memory
b) Go Allocator
Runtime Go punya allocator yang efisien:
Small objects (<32KB): dialokasikan dari memory pool per-size
Large objects (β₯32KB): langsung dari OS
Stack: setiap goroutine punya stack (mulai 2KB, bisa grow)
c) Garbage Collector
GC Go secara periodik:
Scan semua pointer yang masih dipakai
Tandai object yang masih "hidup"
Bebaskan memory object yang mati
Tidak langsung return ke OS, disimpan di free list untuk reuse
8. Dari Kode Go ke RAM
Mari trace alur lengkap dari kode Go:
package main
func main() {
// Alokasi slice
data := make([]byte, 1024*1024) // 1MB
data[0] = 42
}
Yang terjadi:
STEP 1: Compile Time
ββ Compiler Go: compile ke binary
ββ Binary berisi instruksi mesin untuk CPU
STEP 2: Program Dimulai
ββ OS: Load binary ke memory
ββ OS: Buat process baru
ββ OS: Setup page table kosong untuk process
ββ OS: Setup virtual address space:
β ββ 0x00000000-0x00400000: text (kode program)
β ββ 0x00400000-0x00600000: data (global variables)
β ββ 0x00600000-0xC0000000: heap (dynamic allocation)
β ββ 0xC0000000-0xFFFFFFFF: stack
ββ Go Runtime: Inisialisasi (setup allocator, GC, scheduler)
STEP 3: make([]byte, 1MB)
ββ Go Runtime: "Butuh 1MB"
ββ Go Runtime: Cek memory pool β tidak ada yang cukup
ββ Go Runtime: syscall mmap/brk untuk minta memory dari OS
β ββ Syscall: trap ke kernel mode
β ββ Kernel: "OK, saya reservasi 1MB virtual memory"
β ββ Kernel: Update page table (masih belum allocate physical!)
β ββ Kernel: Return alamat virtual 0x12340000 ke program
ββ Go Runtime: Setup slice header:
β ββ pointer: 0x12340000
β ββ length: 1048576
β ββ capacity: 1048576
ββ Return slice ke kode kamu
STEP 4: data[0] = 42
ββ CPU: Eksekusi instruksi "MOV [0x12340000], 42"
ββ MMU: Translate 0x12340000 β cek page table
ββ MMU: "Eh, page ini belum ada physical mapping!"
ββ CPU: Trigger PAGE FAULT (interrupt)
ββ Kernel: *handle page fault*
β ββ Cari free physical page (misal: 0x8A3F000)
β ββ Update page table: 0x12340000 β 0x8A3F000
β ββ Set permission: read/write
ββ CPU: Retry instruksi
ββ MMU: Translate 0x12340000 β 0x8A3F000 (berhasil!)
ββ RAM: Write value 42 ke alamat fisik 0x8A3F000
9. Visualisasi Lengkap
Sempurna! Saya sudah melengkapi visualisasi interaktifnya. Sekarang mari saya tambahkan beberapa penjelasan tambahan yang penting:
10. Copy-on-Write (COW)
Ada mekanisme penting lain yang perlu kamu tahu:
Ketika proses fork (duplikasi proses), tidak semua memory langsung di-copy! Kernel menggunakan Copy-on-Write:
1. Process A fork β Process B
2. Kernel: Copy page table, tapi physical pages SAMA
3. Kernel: Tandai semua pages sebagai "read-only"
4. Process B coba WRITE β page fault!
5. Kernel: "Oh COW page, saya copy sekarang"
6. Kernel: Buat physical page baru, copy data, update page table B
7. Process B lanjut dengan page yang baru
Ini menghemat memory dan waktu saat fork!
11. Huge Pages / Large Pages
Normalnya page size = 4KB, tapi modern CPU support huge pages:
x86-64: 2MB atau 1GB pages
Keuntungan: Lebih sedikit entries di page table, lebih sedikit TLB miss
Go bisa pakai: Transparent Huge Pages (THP) di Linux
12. NUMA (Non-Uniform Memory Access)
Di server dengan multiple CPU socket, RAM tidak "seragam":
[CPU 0] βfastβ [RAM Bank 0]
β slow
[RAM Bank 1] βfastβ [CPU 1]
Akses RAM "lokal" lebih cepat dari RAM "remote". Kernel coba allocate memory dari RAM bank terdekat ke CPU yang eksekusi process.
13. Kenapa Perlu Virtual Memory?
Tanpa virtual memory, masalah besar:
Fragmentasi: Program perlu continuous physical memory (susah!)
Security: Program bisa akses memory program lain (bahaya!)
Relocation: Program harus load di alamat fisik yang sama setiap run
Limited address space: Terbatas physical RAM saja
Dengan virtual memory, semua masalah solved!
Last updated