Rekayasa Performa Linux Kernel Skala Enterprise: Deep-Dive EEVDF Scheduler, Arsitektur Cgroups v2, dan Off-CPU Profiling via eBPF CO-RE
Paradigma Performance Engineering pada Kernel Modern: Dari Heuristik ke Deterministik
Dalam pengelolaan armada server komputasi berskala masif (fleet infrastructure), performa sistem operasi sering kali dipandang secara reduktif sebatas utilisasi CPU rata-rata (load average) atau konsumsi memori persentase. Pada kenyataannya, sistem komputasi berkinerja tinggi (high-throughput, low-latency tier-1) sering kali mengalami degradasi dramatisβseperti lonjakan ekstrim tail latency ($p99$ dan $p99.9$) atau silent system stallβmeskipun utilisasi CPU berada di bawah 40%.
Penyebab dari fenomena paradoksal ini berakar pada ketidakcocokan antara karakteristik beban kerja modern dengan abstraksi subsistem kernel lawas:
- Keterbatasan Completely Fair Scheduler (CFS): CFS yang menjadi standar sejak Linux 2.6.23 mengalokasikan CPU semata-mata berdasarkan bobot keadilan proporsional (fairness), mencampuradukkan antara tugas berlatensi kritis (latency-sensitive) dan tugas batch throughput.
- Fragmentasi Cgroups v1: Hirarki terpisah antar controller (CPU, Memory, Block I/O) pada Cgroups v1 membuat kernel tidak mampu memperhitungkan biaya I/O page-cache writeback ke cgroup pemilik beban kerja aslinya, memicu priority inversion dan alokasi resource tidak terkendali.
- Kebutaan Metrik Tradisional (On-CPU vs. Off-CPU): Alat pemantau konvensional seperti
top,vmstat, dan profiler On-CPU hanya mengamati instruksi saat thread sedang aktif mengeksekusi di core. Ketika sebuah thread mengalami bottleneck karena terblokir menunggu mutex futex, I/O sync, atau memory compaction, thread tersebut menghilang dari radar profiler On-CPU.
Artikel ini membedah arsitektur internal Linux Kernel generasi modern (Linux 6.6+): transisi revolusioner menuju EEVDF (Earliest Eligible Virtual Deadline First), tata kelola isolasi memori serta storage melalui Cgroups v2 Unified Hierarchy, pencegahan Direct Reclaim stall berbasis Pressure Stall Information (PSI), serta teknik diagnosa presisi menggunakan Off-CPU Continuous Profiling via eBPF CO-RE. Seluruh skenario, diagram, dan konfigurasi disajikan dengan data sintetis sesuai standar RFC 5737.
1. Anatomi Scheduler: Transisi dari CFS ke EEVDF (Linux 6.6+)
Sejak diperkenalkan oleh Ingo Molnar, Completely Fair Scheduler (CFS) memodelkan sistem ideal komputasi paralel (Ideal Multi-tasking CPU) di mana setiap proses menerima $1/N$ daya komputasi secara kontinu. CFS melacak variabel waktu maya yang disebut vruntime (virtual runtime):
$$\Delta vruntime_i = \Delta t_{\text{exec}} \times \frac{w_0}{w_i}$$
Di mana $w_0$ adalah bobot default (NICE_0_LOAD = 1024) dan $w_i$ adalah bobot proses berdasarkan nilai nice. Thread dengan vruntime terendah (node paling kiri pada Red-Black Tree) selalu dipilih untuk dieksekusi berikutnya.
Kelemahan Mendasar CFS pada Beban Interaktif
CFS hanya menjamin keadilan jangka panjang (long-term fairness), bukan kepatuhan latensi jangka pendek (short-term latency deadline). Sebuah thread yang baru bangun dari status tidur (misalnya menerima paket jaringan pada socket gRPC) harus antri di belakang thread batch compute yang sedang berjalan jika selisih vruntime-nya tidak melampaui sched_wakeup_granularity_ns. Akibatnya, request mikroservis mengalami jitter latensi acak.
Mekanika EEVDF (Earliest Eligible Virtual Deadline First)
Diadopsi secara penuh sejak Linux 6.6, Peter Zijlstra mengimplementasikan algoritma EEVDF yang memisahkan status hak proses menjadi dua dimensi independen: Kelayakan (Eligibility) dan Batas Waktu Maya (Virtual Deadline).
========================================================================================
LINUX CPU SCHEDULER EVOLUTION: CFS vs EEVDF MECHANICS
========================================================================================
--- [ CFS: COMPLETELY FAIR SCHEDULER (Kernel < 6.6) ] ---
Setiap thread 'i' memiliki vruntime tunggal:
vruntime_i += delta_exec * (NICE_0_LOAD / se->load.weight)
Pick Next: Node paling kiri (leftmost) pada RB-Tree (vruntime terkecil).
Kelemahan: Mengabaikan toleransi latensi task interaktif; rawan jitter.
--- [ EEVDF: EARLIEST ELIGIBLE VIRTUAL DEADLINE FIRST (Kernel >= 6.6) ] ---
[ Virtual Time Base: V(t) = Rata-rata vruntime seluruh runqueue ]
β
βββββββββββββββββββββββββββββββ΄ββββββββββββββββββββββββββββββ
βΌ βΌ
[ Eligibility Test ] [ Virtual Deadline ]
Lag_i = V(t) - vruntime_i d_i = e_i + (q_i / w_i)
Thread 'Eligible' jika: d_i = deadline maya
Lag_i >= 0 (Belum memakan jatah CPU) q_i = slice alokasi waktu
w_i = bobot (nice value)
β β
βββββββββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββ
β
βΌ
[ Selection Rule: Pilih task yang ELIGIBLE
dengan VIRTUAL DEADLINE (d_i) TERKECIL ]
========================================================================================
Rumusan Matematis EEVDF:
- Virtual Time $V(t)$: Sumbu waktu maya sistem yang merepresentasikan rata-rata konsumsi komputasi tertimbang seluruh tugas aktif di runqueue: $$V(t_2) - V(t_1) = \frac{\Delta t}{\sum_{j \in \text{runqueue}} w_j}$$
- Lag Metric ($Lag_i$): Kuantitas yang mengukur surplus atau defisit waktu komputasi yang menjadi hak tugas $i$:
$$Lag_i = w_i \cdot V(t) - vruntime_i$$
- $Lag_i \ge 0$ (Eligible): Tugas belum menggunakan alokasi proporsionalnya. Tugas berhak untuk dipilih.
- $Lag_i < 0$ (Ineligible): Tugas telah mengonsumsi CPU melebihi alokasi proporsionalnya (over-serviced). Tugas ditahan sampai waktu maya $V(t)$ mengejar surplus tersebut.
- Virtual Deadline ($d_i$): $$d_i = e_i + \frac{q_i}{w_i}$$ Di mana $e_i$ adalah waktu saat tugas berstatus eligible, dan $q_i$ adalah durasi kuota waktu (time slice) yang diminta. Tugas dengan alokasi slice lebih kecil ($q_i \ll$) akan memiliki $d_i$ lebih awal, memungkinkannya memotong (preempt) tugas komputasi masif tanpa melanggar prinsip keadilan matematis.
2. Subsistem Memori: Watermark Zone, Direct Reclaim, dan NUMA
Subsistem virtual memory Linux membagi memori fisik menjadi beberapa zone (ZONE_DMA32, ZONE_NORMAL, ZONE_MOVABLE). Kestabilan sebuah node produksi ditentukan oleh bagaimana kernel mengelola transisi antara alokasi cepat (Fast Path) dan pembersihan paksa (Slow Path).
+---------------------------------------------------------------------------------------+
| LINUX MEMORY MANAGEMENT & RECLAIM PIPELINE |
+---------------------------------------------------------------------------------------+
β
Alokasi Memori Baru (alloc_pages)
β
βΌ
+-------------------------------------------------+
| Periksa Watermark Zone: |
| Free Pages > WMARK_LOW ? |
+-------------------------------------------------+
β β
[ YA ] [ TIDAK ]
βΌ βΌ
Alokasi Instan Selesai Bangunkan Daemon Kernel:
(Fast Path, Sub-microsec) [ kswapd ] di background
β
βΌ
+-----------------------------+
| Free Pages > WMARK_MIN ? |
+-----------------------------+
β β
[ YA ] [ TIDAK ]
β β
βΌ βΌ
kswapd membersihkan [ DIRECT RECLAIM ]
Page Cache di bg Aplikasi dibekukan!
(Slow Path Ringan) (Latency Spike P99!)
β
βΌ
+---------------------+
| Gagal membebaskan? |
+---------------------+
β
βΌ
[ OOM KILLER INVOKED ]
Mekanisme Watermark
Kernel menghitung tiga ambang batas memori berdasarkan nilai vm.min_free_kbytes:
- $WMARK_MIN$: Cadangan memori mutlak kernel untuk interupsi kritis (
GFP_ATOMIC). Jika kapasitas memori bebas menyentuh batas ini, seluruh alokasi normal pengguna dialihkan ke mode Direct Reclaim. - $WMARK_LOW$: Titik picu di mana thread kernel
kswapdbangun di latar belakang untuk melakukan pemindaian LRU (Least Recently Used) dan melepaskan clean page cache atau menjadwalkan penulisan dirty pages. $$WMARK_LOW = WMARK_MIN + \frac{WMARK_MIN}{4}$$ - $WMARK_HIGH$: Titik di mana
kswapdtelah membebaskan cukup ruang dan kembali memasuki status dorman (sleep). $$WMARK_HIGH = WMARK_MIN + \frac{WMARK_MIN}{2}$$
Pada server berkapasitas RAM besar ($\ge 128,\text{GB}$), nilai default vm.min_free_kbytes sering kali terlalu kecil ($\approx 67,\text{MB}$). Saat terjadi lonjakan alokasi memori mendadak (misalnya in-memory cache burst), memori bebas dapat menembus $WMARK_LOW$ dan anjlok di bawah $WMARK_MIN$ sebelum kswapd sempat merespons. Akibatnya, aplikasi pengguna langsung mengalami Direct Reclaim Stall, di mana proses aplikasi dibekukan selama ratusan milidetik untuk menulis data kotor ke storage.
3. Cgroups v2 Unified Hierarchy: Arsitektur & Kontrol Perlindungan
Berbeda dengan Cgroups v1 yang memisahkan hirarki per controller, Cgroups v2 mengadopsi struktur pohon tunggal (unified hierarchy) di /sys/fs/cgroup. Desain ini memungkinkan pelacakan konsumsi sumber daya yang terintegrasi penuh antara memori, CPU, dan writeback I/O.
/sys/fs/cgroup (Root)
β
ββββββββββββββββββββββββ΄βββββββββββββββββββββββ
βΌ βΌ
system.slice workload.slice
(System Daemons: sshd, udev) (Tier-1 Production Apps)
β β
βββββββββββββ΄ββββββββββββ βββββββββββββ΄ββββββββββββ
βΌ βΌ βΌ βΌ
sshd.service node-exporter api-gateway.service db-primary.service
cpu.weight=100 cpu.weight=50 cpu.weight=800 cpu.weight=1000
memory.high=256M memory.high=128M memory.min=8G memory.min=16G
memory.max=512M memory.max=256M memory.high=14G memory.high=30G
memory.max=16G memory.max=32G
io.weight=800 io.weight=1000
Model Proteksi Memori Cgroups v2:
memory.min(Hard Protection): Jaminan kapasitas memori yang pantang direclaim oleh kernel dalam kondisi apa pun. Jika penggunaan cgroup berada di bawah batas ini, kernel lebih memilih membunuh cgroup lain melalui OOM killer daripada merebut halamannya. Sangat krusial untuk database utama.memory.low(Soft Protection): Memberikan perlindungan best-effort. Memori hanya akan dipindai dan diambil jika tidak ada cgroup non-prioritas lain yang dapat direclaim.memory.high(Throttle Boundary): Ambang batas pembatasan halus. Ketika proses melampaui nilai ini, proses tidak dimatikan, melainkan kernel memperlambat siklus alokasi proses tersebut dan memprioritaskan penulisan page cache ke disk secara proporsional terhadap kelebihan memori.memory.max(Hard Limit): Batas mutlak memori. Pelanggaran batas ini memicu Direct Reclaim internal cgroup; jika tetap gagal membebaskan halaman, proses di dalam cgroup akan dieliminasi oleh OOM Killer.
4. Konfigurasi Produksi Tingkat Enterprise
Berikut adalah rangkaian artefak konfigurasi siap pakai (production-grade chassis) untuk mengoptimalkan node komputasi performa tinggi.
4.1 Enterprise Sysctl Tuning (/etc/sysctl.d/99-performance-kernel-enterprise.conf)
Konfigurasi ini mengoptimalkan parameter Virtual Memory, CPU Scheduler, Batasan File Descriptor, dan BPF JIT Compiler:
# ==============================================================================
# ENTERPRISE LINUX PERFORMANCE TUNING CONFIGURATION
# File: /etc/sysctl.d/99-performance-kernel-enterprise.conf
# Environment: Tier-1 Production Host (Bare-Metal & Cloud NVMe)
# Data Reference: 100% Synthetic RFC 5737 Compliant
# ==============================================================================
# ------------------------------------------------------------------------------
# 1. SUBSISTEM VIRTUAL MEMORY (VM) & PAGE CACHE
# ------------------------------------------------------------------------------
# Cadangkan ~1GB memori darurat untuk mencegah Direct Reclaim kswapd stall
vm.min_free_kbytes = 1048576
# Batasi akumulasi dirty memory berbasis byte absolut (bukan persentase)
# Mulai penulisan background saat dirty data menyentuh 256MB
vm.dirty_background_bytes = 268435456
# Bekukan proses pemanggil jika akumulasi dirty data menyentuh 1GB
vm.dirty_bytes = 1073741824
# Interval flush thread kworker (500 centisecs = 5 detik)
vm.dirty_writeback_centisecs = 500
vm.dirty_expire_centisecs = 3000
# Tekan kecenderungan swap tanpa mematikannya total (katup pengaman)
vm.swappiness = 10
# Cegah kernel membuang dentry dan inode cache terlalu agresif
vm.vfs_cache_pressure = 50
# Matikan zone_reclaim_mode untuk mencegah CPU lockup akibat lokal NUMA thrashing
vm.zone_reclaim_mode = 0
# Overcommit heuristik terkontrol
vm.overcommit_memory = 0
vm.overcommit_ratio = 50
# Aktifkan Pressure Stall Information (PSI)
vm.psi = 1
# ------------------------------------------------------------------------------
# 2. CPU SCHEDULER & GRANULARITAS TASK
# ------------------------------------------------------------------------------
# Granularitas minimum eksekusi task sebelum preemption (3ms)
kernel.sched_min_granularity_ns = 3000000
# Target latensi penjadwalan runqueue (12ms)
kernel.sched_latency_ns = 12000000
# Granularitas preemption untuk task yang baru bangun (2ms)
kernel.sched_wakeup_granularity_ns = 2000000
# Nonaktifkan autogrouping sesi tty agar prioritas service background tidak turun
kernel.sched_autogroup_enabled = 0
# Biaya migrasi cache antar core CPU (500us)
kernel.sched_migration_cost_ns = 500000
# ------------------------------------------------------------------------------
# 3. FILE SYSTEM & RESOURCE LIMITS
# ------------------------------------------------------------------------------
# Batas global file descriptor terbuka di sistem (16 Juta)
fs.file-max = 16777216
fs.nr_open = 10485760
# Optimasi batas inotify untuk container daemons & log shippers
fs.inotify.max_user_instances = 8192
fs.inotify.max_user_watches = 1048576
fs.inotify.max_queued_events = 32768
# Batas asynchronous I/O kernel
fs.aio-max-nr = 1048576
# ------------------------------------------------------------------------------
# 4. KERNEL FAULT HANDLING & RECOVERY
# ------------------------------------------------------------------------------
# Reboot otomatis 10 detik setelah Kernel Panic
kernel.panic = 10
kernel.panic_on_oops = 1
vm.panic_on_oom = 0
# Matikan NMI Watchdog untuk menghemat siklus interupsi di node latensi kritis
kernel.nmi_watchdog = 0
# ------------------------------------------------------------------------------
# 5. eBPF JIT & SECURITY HARDENING
# ------------------------------------------------------------------------------
# Kompilasi JIT bytecode eBPF langsung ke machine code native
net.core.bpf_jit_enable = 1
net.core.bpf_jit_harden = 1
net.core.bpf_jit_limit = 1073741824
# Batasi pemanggilan bpf() hanya untuk proses dengan kapabilitas CAP_BPF / CAP_SYS_ADMIN
kernel.unprivileged_bpf_disabled = 1
Terapkan parameter tanpa melakukan restart sistem:
sysctl -p /etc/sysctl.d/99-performance-kernel-enterprise.conf
4.2 Parameter Bootloader GRUB Low-Latency (/etc/default/grub.d/99-latency-tuning.cfg)
Konfigurasi kernel boot command-line untuk mematikan mode hemat daya dalam (deep C-states), mengunci governor CPU, dan mengaktifkan isolasi I/O:
# /etc/default/grub.d/99-latency-tuning.cfg
# Konfigurasi boot loader parameter untuk node komputasi performa tinggi
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash \
processor.max_cstate=1 \
intel_idle.max_cstate=1 \
cpufreq.default_governor=performance \
transparent_hugepage=madvise \
psi=1 \
skew_tick=1 \
rcupdate.rcu_expedited=1 \
elevator=none \
nvme_core.default_ps_max_latency_us=0"
Analisis Parameter Kunci:
processor.max_cstate=1&intel_idle.max_cstate=1: Mencegah transisi core CPU ke status tidur dalam ($C_6/C_7$). Waktu bangun (wake-up latency) dari C-state dalam memerlukan durasi hingga puluhan mikrodetik yang merusak kestabilan $p99.9$.transparent_hugepage=madvise: Mencegah daemonkhugepagedmelakukan defragmentasi memori secara global yang memicu latensi acak. Modemadvisemembatasi HugePages hanya pada aplikasi yang secara eksplisit meminta alokasi melalui panggilan sistemmadvise(..., MADV_HUGEPAGE).elevator=none: Menetapkan no-op I/O scheduler secara global untuk block device NVMe PCIe.nvme_core.default_ps_max_latency_us=0: Mengunci kontroler NVMe pada level performa aktif penuh tanpa Power State throttling.
Perbarui konfigurasi GRUB dan initramfs:
update-grub && update-initramfs -u
4.3 Definisi Systemd Cgroups v2 Hardened Slice (/etc/systemd/system/workload.slice)
Membangun alokasi sumber daya terisolasi untuk unit mikroservis tier-1 dengan jaminan memori dan bobot komputasi terproteksi:
# /etc/systemd/system/workload.slice
[Unit]
Description=Tier-1 Mission Critical Workload Slice (Cgroups v2 Hardened)
DefaultDependencies=no
Before=slices.target
[Slice]
# Alokasi bobot CPU tinggi di scheduler EEVDF (skala 1-10000, default = 100)
CPUWeight=800
# 1. Jaminan Mutlak: 8GB memori TIDAK PERNAH direclaim dalam kondisi apa pun
MemoryMin=8589934592
# 2. Jaminan Best-Effort: 16GB diproteksi sebelum cgroup non-prioritas direclaim
MemoryLow=17179869184
# 3. Batas Throttle: Di atas 28GB, alokasi memori proses diperlambat secara proporsional
MemoryHigh=30064771072
# 4. Batas Mutlak: Maksimum 32GB memori fisik
MemoryMax=34359738368
# Matikan alokasi swap pada slice ini untuk mencegah degradasi latensi disk I/O
MemorySwapMax=0
# Bobot antrian I/O multi-queue pada SSD/NVMe (Rentang 1-10000)
IOWeight=800
# Batasi jumlah thread/task untuk mencegah kegagalan fork exhaustion
TasksMax=65535
Tautkan unit mikroservis (misalnya api-gateway.service) ke dalam workload.slice:
# /etc/systemd/system/api-gateway.service.d/override.conf
[Service]
Slice=workload.slice
Restart=always
RestartSec=3s
LimitNOFILE=1048576
LimitMEMLOCK=infinity
Muat ulang daemon dan restart service:
systemctl daemon-reload
systemctl restart api-gateway.service
5. Script Otomatisasi Diagnostik & Observabilitas eBPF
Tiga artefak skrip operasional untuk melakukan validasi subsistem kernel, stress-testing latensi penjadwalan, serta penelusuran off-CPU blocking call stack.
5.1 eBPF Off-CPU Bottleneck Tracer via bpftrace (ebpf-offcpu-flamegraph.sh)
Skrip ini mengaitkan (hook) probe eBPF pada tracepoint scheduler kernel (sched:sched_switch), menghitung durasi tidur thread saat terlepas dari CPU, dan menghasilkan histogram latensi mikrodetik secara efisien:
#!/usr/bin/env bash
# ==============================================================================
# SCRIPT: ebpf-offcpu-flamegraph.sh
# AUTHOR: La Nina π
# DESCRIPTION: eBPF Low-Overhead Off-CPU Latency Tracer using bpftrace CO-RE
# DATA REF: 100% Synthetic Benchmark (RFC 5737 Compliant)
# ==============================================================================
set -euo pipefail
DURATION="${1:-15}"
TARGET_COMM="${2:-}"
OUTPUT_FILE="/tmp/offcpu_trace_$(date +%s).txt"
RED='\033[0;31m'
GREEN='\033[0;32m'
CYAN='\033[0;36m'
NC='\033[0m'
if ! command -v bpftrace >/dev/null 2>&1; then
echo -e "${RED}[-] bpftrace tidak ditemukan. Jalankan: apt-get install -y bpftrace${NC}"
exit 1
fi
echo -e "${CYAN}======================================================================${NC}"
echo -e "${CYAN} eBPF OFF-CPU STACK TRACER & BOTTLENECK DIAGNOSTIC ENGINE ${NC}"
echo -e "${CYAN} Durasi: ${DURATION}s | Target Filter: ${TARGET_COMM:-[SEMUA PROSES]} ${NC}"
echo -e "${CYAN}======================================================================${NC}"
bpftrace -e '
#include <linux/sched.h>
BEGIN {
printf("Melacak off-CPU latency via eBPF... Tekan Ctrl-C atau tunggu %d detik.\n", '"$DURATION"');
}
tracepoint:sched:sched_switch {
// 1. Task yang sedang dilepas dari CPU (prev)
$prev_pid = args->prev_pid;
@start[$prev_pid] = nsecs;
@stack_map[$prev_pid] = kstack;
// 2. Task yang sedang naik ke CPU (next)
$next_pid = args->next_pid;
if (@start[$next_pid]) {
$delta_us = (nsecs - @start[$next_pid]) / 1000;
// Catat sampel hanya jika durasi blokir melebihi ambang batas 100us
if ($delta_us > 100) {
@offcpu_latency_hist[args->next_comm] = hist($delta_us);
@offcpu_total_time_us[args->next_comm] = sum($delta_us);
}
delete(@start[$next_pid]);
delete(@stack_map[$next_pid]);
}
}
interval:s:'"$DURATION"' {
exit();
}
END {
printf("\n=== TOP OFF-CPU BLOCKED COMMANDS BY TOTAL TIME (MICROSECONDS) ===\n");
}
' > "$OUTPUT_FILE" 2>&1
echo -e "\n${GREEN}[β] Tracing selesai. Artefak telemetri disimpan di: $OUTPUT_FILE${NC}"
echo -e "${CYAN}--- Ringkasan Data Latensi Terdeteksi ---${NC}"
tail -n 25 "$OUTPUT_FILE"
5.2 Memory Fragmentation & PSI Health Auditor (validate-kernel-memory-psi.sh)
Skrip auditing otonom untuk mengevaluasi saturasi Pressure Stall Information (PSI), rasio kotoran page cache, dan indeks fragmentasi alokator memori:
#!/usr/bin/env bash
# ==============================================================================
# SCRIPT: validate-kernel-memory-psi.sh
# AUTHOR: La Nina π
# DESCRIPTION: Deep Audit of Linux Memory Subsystem, Compaction, PSI & NUMA
# DATA REF: 100% Synthetic Benchmark (RFC 5737 Compliant)
# ==============================================================================
set -euo pipefail
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
NC='\033[0m'
echo -e "${CYAN}======================================================================${NC}"
echo -e "${CYAN} ENTERPRISE LINUX MEMORY & PSI HEALTH AUDITOR ${NC}"
echo -e "${CYAN} Host Target: node-01.infra.test (192.0.2.10) ${NC}"
echo -e "${CYAN}======================================================================${NC}"
# 1. Audit Metrik Pressure Stall Information (PSI)
echo -e "\n${YELLOW}[1/3] Memeriksa Pressure Stall Information (PSI)...${NC}"
for res in cpu memory io; do
if [ -f "/proc/pressure/$res" ]; then
echo -e "${CYAN}--- Metrik PSI: $res ---${NC}"
cat "/proc/pressure/$res"
SOME_10=$(grep "some" "/proc/pressure/$res" | sed -n 's/.*avg10=\([0-9.]*\).*/\1/p')
if (( $(echo "$SOME_10 > 5.0" | bc -l 2>/dev/null || echo 0) )); then
echo -e "${RED}[PERINGATAN TINGGI] Tekanan $res stall melampaui toleransi: avg10 = $SOME_10%${NC}"
else
echo -e "${GREEN}[LOLOS] Tekanan $res optimal (avg10 = $SOME_10%)${NC}"
fi
fi
done
# 2. Audit Fragmentasi Buddy Allocator
echo -e "\n${YELLOW}[2/3] Memeriksa Fragmentasi Memori (/proc/buddyinfo)...${NC}"
echo -e "Order: 0(4K) 1(8K) 2(16K) 3(32K) 4(64K) 5(128K) 6(256K) 7(512K) 8(1M) 9(2M) 10(4M)"
cat /proc/buddyinfo
# 3. Audit Akumulasi Dirty Page Cache
echo -e "\n${YELLOW}[3/3] Memeriksa Akumulasi Page Cache Dirty Buffer...${NC}"
MEM_TOTAL=$(grep "MemTotal:" /proc/meminfo | awk '{print $2}')
DIRTY=$(grep "Dirty:" /proc/meminfo | awk '{print $2}')
WRITEBACK=$(grep "Writeback:" /proc/meminfo | awk '{print $2}')
DIRTY_PCT=$(echo "scale=2; ($DIRTY / $MEM_TOTAL) * 100" | bc -l)
echo -e " - Total Kapasitas RAM : $((MEM_TOTAL / 1024)) MB"
echo -e " - Buffer Data Kotor : $((DIRTY / 1024)) MB (${DIRTY_PCT}%)"
echo -e " - In-Flight Writeback : $((WRITEBACK / 1024)) MB"
if (( $(echo "$DIRTY_PCT > 10.0" | bc -l) )); then
echo -e "${RED}[BAHAYA] Buffer kotor melampaui batas aman. Risiko Direct Reclaim stall!${NC}"
else
echo -e "${GREEN}[LOLOS] Alokasi dirty memory terkontrol ketat.${NC}"
fi
echo -e "\n${GREEN}[β] Seluruh audit subsistem memori selesai dijalankan.${NC}"
6. Skenario Troubleshooting Kasus Nyata (Root Cause Analysis)
Berikut adalah studi kasus mendalam mengenai anomali latensi yang umum terjadi di lingkungan komputasi berkinerja tinggi beserta langkah mitigasinya.
========================================================================================
STUDI KASUS: ANOMALI CFS QUOTA THROTTLING
========================================================================================
CFS Period Window = 100ms (Batas CPU Limit = 2 Core -> Kuota = 200ms)
0ms 12.5ms 100ms
βββββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββ
β 16 Thread Pool Bursty Task β KERNEL MEMBEKUKAN PROSES β
β Konsumsi Kuota 200ms CPU Habisβ (CFS QUOTA THROTTLED) β
β (16 threads * 12.5ms = 200ms) β Aplikasi tidak merespons selama 87.5ms! β
βββββββββββββββββββββββββββββββββ΄βββββββββββββββββββββββββββββββββββββββββββ
[ Utilisasi Rata-Rata CPU: 35% ] βββΊ [ Tail Latency p99 Melejit Hingga 900ms ]
========================================================================================
Kasus 1: Lonjakan Tail Latency ($p99$) Akibat CFS Quota Throttling pada Utilisasi Rendah
- Gejala: Layanan API backend di kluster Kubernetes dengan limit
resources.limits.cpu: "2"melaporkan rata-rata utilisasi CPU hanya berkisar antara 35% - 40%. Namun, metrik latensi $p99$ melonjak dari $15,\text{ms}$ menjadi $900,\text{ms}$ secara acak. - Akar Masalah (RCA): CFS mengalokasikan kuota dalam jendela waktu diskrit
cpu.cfs_period_us($100,\text{ms}$). Limit2 CPUsetara dengan kuota waktu komputasi $200.000,\mu\text{s}$ per siklus $100,\text{ms}$. Ketika layanan menerima lonjakan request simultan, 16 thread pekerja berjalan bersamaan dan menghabiskan total kuota $200,\text{ms}$ CPU hanya dalam waktu $12.5,\text{ms}$ pertama. Akibatnya, untuk sisa waktu $87.5,\text{ms}$, seluruh thread di dalam cgroup dibekukan oleh kernel hingga siklus periode berikutnya dimulai. - Solusi Rekayasa:
- Aktifkan fitur CPU Burst (
cpu.cfs_burst_us) pada Cgroups v2 untuk mengakumulasi sisa kuota yang tidak terpakai dari periode sebelumnya:echo 100000 > /sys/fs/cgroup/workload.slice/cpu.max.burst - Perkecil periode CFS dari $100,\text{ms}$ menjadi $10,\text{ms}$ (
cpu.cfs_period_us = 10000). Periode yang lebih pendek memperkecil durasi beku (freeze duration) dari $87.5,\text{ms}$ menjadi hanya $\approx 8.7,\text{ms}$. - Pada arsitektur microservices modern, hapus
cpu limitsdan andalkan penjaminancpu requestsberbasis QoS Burstable/Guaranteed.
- Aktifkan fitur CPU Burst (
Kasus 2: System Freeze dan Compaction Stall Akibat Dirty Memory Thrashing
- Gejala: Node database PostgreSQL master pada host
db-node1.data.internal(198.51.100.25) mengalami freeze total selama 4 hingga 8 detik saat menjalankan backup streaming berkala. Seluruh koneksi klien mengalami timeout. - Akar Masalah (RCA): Pengaturan bawaan sistem menyetel
vm.dirty_ratio = 20. Pada host dengan RAM 256GB, kernel mengizinkan akumulasi memori kotor hingga $51.2,\text{GB}$ sebelum memaksakan sinkronisasi disk. Ketika batas tercapai pada storage dengan throughput penulisan terbatas ($300,\text{MB/s}$), proses alokasi memori PostgreSQL terjerumus ke dalam Direct Reclaim: thread kernel mengunci alokasi halaman baru dan memaksa aplikasi pengguna menunggu flushing $51.2,\text{GB}$ data kotor ke disk. - Solusi Rekayasa:
Ganti rasio persentase dinamis dengan ambang batas byte mutlak pada
/etc/sysctl.d/99-performance-kernel-enterprise.conf:vm.dirty_bytes = 1073741824 # Maksimum 1GB data kotor vm.dirty_background_bytes = 268435456 # Mulai flushing latar belakang pada 256MB
Kasus 3: Latensi Remote NUMA Access dan Interconnect Contention
- Gejala: Instance database in-memory mengalami degradasi throughput hingga 40% dan lonjakan siklus CPU stalled ketika ukuran dataset melampaui separuh kapasitas memori fisik host dual-socket.
- Akar Masalah (RCA): Proses dialokasikan pada Socket CPU 0, namun alokasi memorinya dialokasikan ke Node NUMA 1 melalui bus interkoneksi eksternal (UPI / Infinity Fabric). Latensi akses DRAM lokal adalah $\approx 75,\text{ns}$, sedangkan akses DRAM remote membutuhkan $\approx 160,\text{ns}$. Pemeriksaan menggunakan hardware counters membuktikan bahwa rasio
node-load-missesmenyentuh 65%. - Solusi Rekayasa:
Jalankan beberapa instance independen yang dipin secara eksklusif ke node NUMA masing-masing menggunakan
numactl:# Instance Alpha: Terisolasi pada NUMA Node 0 numactl --cpunodebind=0 --membind=0 /usr/bin/engine-service --config=/etc/engine/node0.conf # Instance Beta: Terisolasi pada NUMA Node 1 numactl --cpunodebind=1 --membind=1 /usr/bin/engine-service --config=/etc/engine/node1.conf
7. Matriks Tata Kelola & Evaluasi Parameter Kritis
| Komponen Subsistem | Parameter Kernel / File | Nilai Produksi Rekomendasi | Dampak Terhadap SLA & Latensi |
|---|---|---|---|
| Scheduler | kernel.sched_autogroup_enabled | 0 | Mengeliminasi distorsi prioritas background daemons. |
| Scheduler | cpu.cfs_burst_us | 100000 | Memangkas false-positive $p99$ throttling akibat request burst. |
| Virtual Memory | vm.dirty_bytes | 1073741824 (1GB) | Mencegah pembekuan Direct Reclaim saat I/O writeout masif. |
| Virtual Memory | vm.min_free_kbytes | 1048576 (1GB) | Memberikan buffer aman bagi interupsi jaringan berkecepatan tinggi. |
| Cgroups v2 | MemoryMin & MemoryLow | Alokasi Eksak Byte | Proteksi mutlak database tier-1 dari eksekusi OOM Killer. |
| Storage Block Layer | I/O Elevator | none (NVMe PCIe) | Mengeliminasi overhead software queue pada controller hardware modern. |
| Observabilitas | eBPF bpftrace Hook | On-CPU + Off-CPU | Identifikasi presisi thread stall pada antrian futex dan sleep syscall. |
Melalui implementasi arsitektur EEVDF scheduler, pengondisian Cgroups v2 terpadu, dan observabilitas kontinu berbasis eBPF Off-CPU profiling, infrastruktur Linux skala enterprise dapat beroperasi secara deterministik, meminimalkan anomali latensi ekstrim, serta mengoptimalkan throughput komputasi hingga batas kapasitas hardware fisik.