Bali, Indonesia
Insights

Ketika TCP Slow Receiver Mengunci HBM: Anatomi Backpressure Kernel Buffer pada LLM Streaming Cluster

Invalid Date
0:00
Laporan kapasitas dari ClearML berjudul Inference Is the New Bottleneck: How to Plan GPU Capacity for Production AI memotret realitas pahit di lantai data center hari ini: lebih dari dua pertiga komputasi AI global telah bergeser dari training ke inference. Di balik angka belanja infrastruktur bernilai miliaran dolar untuk pengadaan H100 dan B200, ada anomali operasional yang kerap membuat tim platform frustrasi: utilisasi tensor core GPU anjlok drastis bukan karena modelnya kurang optimal atau prompt-nya terlalu panjang, melainkan karena client di ujung koneksi seluler lambat membaca respons token via HTTP Server-Sent Events (SSE). Ketika kita melayani jutaan token per detik menggunakan arsitektur continuous batching modern, asumsi bahwa lapisan jaringan (L4/L7) terisolasi sepenuhnya dari manajemen memori GPU (HBM) adalah kekeliruan fatal. Satu slow receiver di jaringan publik bisa mengunci alokasi KV-cache di High Bandwidth Memory selama puluhan detik, menciptakan efek domino yang melumpuhkan throughput satu node inferensi penuh.
Untuk memahami bagaimana paket TCP yang tersendat bisa menyandera memori berkecepatan 3 TB/s di GPU, kita harus melihat bagaimana inference engine menyalurkan token ke pengguna. Setiap token yang dihasilkan oleh autoregressive loop dieksekusi per batch step. Token teks dikonversi menjadi potongan HTTP chunked atau event SSE, lalu dilempar ke network socket melalui syscall write(2) atau send(2) di tingkat runtime aplikasi. Masalah bermula ketika client mengalami degradasi jaringan atau thread parsing sisi client terblokir. TCP receive window (rcv_wnd) milik client akan mengecil hingga menyentuh angka nol (Zero Window). Kernel Linux di host inferensi segera mendeteksi ini dan berhenti mengosongkan socket send buffer (SO_SNDBUF). Dalam hitungan milidetik, buffer socket terisi penuh. Event loop asynchronous di web server (seperti uvloop atau Tokio) yang bertugas mem-push token terpaksa menahan eksekusi coroutine streaming karena socket tidak lagi berstatus writable. Di sinilah jurang pemisah antara network stack dan GPU memory manager runtuh. Scheduler inferensi (misalnya pada vLLM atau SGLang) menganggap sebuah request aktif sampai generator token benar-benar selesai dan socket berhasil ditutup. Karena coroutine streaming tertahan di kernel buffer, status request tidak pernah berpindah ke state FINISHED. Akibatnya, block manager pada GPU menolak melepaskan halaman blok KV-cache milik request tersebut dari HBM. Memori puluhan gigabyte yang seharusnya bisa langsung di-reuse untuk prompt berikutnya justru tersandera menunggu ACK dari jaringan seluler yang bapuk.
Pada arsitektur non-streaming tradisional, request dihitung sampai tuntas, KV-cache langsung dibebaskan, dan payload utuh disimpan di memori host sebelum dikirim. Namun pada model streaming interaktif, KV-cache harus tetap hidup di HBM selama token masih terus diproduksi dan disalurkan. Algoritma continuous batching mengalokasikan slot dinamis per iterasi step forward pass. Ketika ketersediaan blok KV-cache bebas di HBM menipis akibat request-request lambat yang menumpuk, scheduler dihadapkan pada dua pilihan buruk saat ada prompt baru masuk: preempt request yang sedang berjalan atau menahan request baru di antrean kedatangan (waiting queue). Jika scheduler memilih preempting, blok KV-cache dari request aktif akan di-swap keluar dari HBM menuju CPU DRAM via bus PCIe, atau bahkan di-drop total dan dipaksa recompute dari awal saat slot tersedia kembali.
BASH
# Memantau antrean TCP socket send buffer yang tersumbat pada port inferensi
ss -t -i 'sport = :8000' | awk '{print 1,2, 3,4, $5}'
# Perhatikan kolom Send-Q: angka yang membengkak menandakan backpressure ke runtime
Begitu swapping ke CPU DRAM terjadi, bus PCIe mengalami saturasi bandwidth. Time-to-First-Token (TTFT) untuk request baru melonjak hingga ratusan persen, sementara Inter-Token Latency (ITL) untuk pengguna lain yang satu batch mengalami jitter parah. Kapasitas komputasi GPU yang berharga habis terbuang bukan untuk inferensi matriks, melainkan untuk stall cycle menunggu manajemen paging memori darurat yang dipicu oleh kemacetan TCP socket.
Menyelesaikan problem backpressure ini membutuhkan decoupling tegas antara siklus hidup KV-cache di HBM dengan siklus transmisi socket di kernel Linux. Engine scheduler tidak boleh disandera oleh kecepatan transmisi layer 4. Ada tiga prinsip arsitektur yang wajib diterapkan pada kluster inferensi skala produksi: Pertama, terapkan decoupled egress buffer di memori host (CPU RAM). Inference engine harus langsung membebaskan blok KV-cache di HBM segera setelah token terakhir selesai digenerasi (finish_reason: stop), tanpa menunggu socket client mengonfirmasi penerimaan seluruh chunk. Token-token yang sudah selesai digenerasi ditampung dalam ring-buffer kecil di memori host yang dikelola oleh reverse proxy berkinerja tinggi (seperti Envoy atau NGINX) sebelum dialirkan ke client. Kedua, terapkan timeout agresif berbasis socket write readiness. Jika socket send buffer tertahan penuh melampaui ambang batas toleransi (misalnya 2 hingga 3 detik), reverse proxy atau middleware runtime harus langsung memutuskan koneksi (mengirimkan TCP RST) dan membatalkan request (early cancellation) di tingkat scheduler engine. Melindungi integritas kapasitas HBM jauh lebih krusial daripada mempertahankan satu client bermasalah yang mengorbankan ratusan pengguna lain di batch yang sama.
YAML
# Konfigurasi proteksi timeout buffer streaming pada Envoy proxy
route_config:
  virtual_hosts:
    - name: llm_backend
      routes:
        - match: { prefix: "/v1/chat/completions" }
          route:
            timeout: 0s # Nonaktifkan timeout global untuk SSE
            idle_timeout: 5s # Putus jika tidak ada data yang mengalir selama 5 detik
            max_stream_duration:
              grpc_timeout_header_max: 120s
Ketiga, optimasi parameter socket kernel host Linux. Jangan biarkan kernel secara otomatis memperbesar SO_SNDBUF (net.ipv4.tcp_wmem) tanpa batas atas yang masuk akal pada node worker GPU. Buffer kernel yang terlalu besar hanya akan menyamarkan masalah (bufferbloat), memperlama waktu deteksi client yang macet, dan menunda sinyal error ke inference runtime. Pergeseran beban kerja menuju inferensi menuntut kita berpikir melampaui optimasi CUDA kernel semata. Di era di mana GPU HBM adalah aset termahal dan paling terbatas di data center, membiarkan implementasi socket streaming primitif mengontrol siklus alokasi memori akselerator adalah resep pasti menuju bencana performa.