Belajar WebSocket - Performance Optimization
Episode 17 of 34

Belajar WebSocket - Performance Optimization

Episode ini membahas membuat aplikasi WebSocket lebih cepat: optimasi koneksi dan payload, clustering Node.js dengan worker, pemantauan event loop, debounce di klien, serta optimasi jaringan dan TLS.

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

Pendahuluan

Aplikasi sudah berfungsi, tapi apakah ia cukup cepat? Di episode ini kita mengukur dan memperbaiki: menekan latensi, mengurangi bandwidth, memanfaatkan semua inti CPU, dan memastikan event loop Node.js tidak tersendat.

Episode 17 membahas performance optimization dari empat sisi: koneksi, pesan, server, dan klien. Kalian akan belajar teknik yang langsung bisa diterapkan, mulai dari kompresi sampai clustering.

Optimasi Koneksi

Keep-Alive dan TCP Tuning

Koneksi WebSocket yang sehat perlu disetel agar tidak boros dan tidak mati sia-sia.

Cek parameter TCP
sysctl net.ipv4.tcp_keepalive_time
sysctl net.ipv4.tcp_keepalive_intvl
sysctl net.ipv4.tcp_keepalive_probes

Parameter tcp_keepalive_time menentukan kapan kernel mulai mengirim paket keep-alive. Untuk koneksi panjang seperti WebSocket, nilai yang wajar (misalnya 60 detik) membuat NAT dan load balancer tidak menghapus koneksi idle.

Socket Buffer

Buffer TCP yang terlalu kecil menahan throughput, terlalu besar menahan memori.

JSSet socket buffer
const wss = new WebSocketServer({
  port: 8080,
  perMessageDeflate: true,
  maxPayload: 64 * 1024,
});

maxPayload: 64 * 1024 membatasi ukuran pesan sehingga satu pesan raksasa tidak menghabiskan memori. Batasan ini juga mencegah serangan yang mengirim payload sangat besar.

Optimasi Pesan

Kompresi dan Payload Minimal

Ukuran pesan adalah bandwidth dan latensi. Tiga cara menguranginya:

JSMeminimalkan payload
const pesan = {
  t: "chat",          // singkatan tipe
  r: "node",          // singkatan room
  m: "Halo!",         // isi pesan
};
 
ws.send(JSON.stringify(pesan));
  • Minify field name: type menjadi t, message menjadi m. Hemat 30-50 persen.
  • Kompresi: aktifkan permessage-deflate untuk payload yang berulang.
  • Binary: untuk angka dan struktur tetap, pakai binary alih-alih teks.

Batching Pesan

Mengirim seratus pesan kecil lebih mahal daripada satu pesan besar.

JSBatch update ke klien
const antrean = [];
 
setInterval(() => {
  if (antrean.length === 0) return;
  ws.send(JSON.stringify({
    type: "batch",
    items: antrean.splice(0, antrean.length),
  }));
}, 100);

antrean.splice(0, antrean.length) mengambil semua update yang terkumpul dalam 100 ms. Posisi mouse yang diupdate 60 kali per detik cukup dikirim 10 kali per detik dalam satu batch.

Optimasi Server

Clustering Node.js

Node.js berjalan pada satu inti CPU. Cluster memanfaatkan semua inti.

JSCluster Node.js untuk WebSocket
const cluster = require("cluster");
const os = require("os");
 
if (cluster.isPrimary) {
  const jumlah = os.cpus().length;
  for (let i = 0; i < jumlah; i++) {
    cluster.fork();
  }
  cluster.on("exit", (worker) => {
    console.log("worker mati, fork ulang:", worker.process.pid);
    cluster.fork();
  });
} else {
  const { WebSocketServer } = require("ws");
  const wss = new WebSocketServer({ port: 8080 });
  wss.on("connection", (ws) => ws.send("terhubung ke worker " + process.pid));
}

cluster.isPrimary membedakan proses utama dan worker. Setiap worker melayani koneksi sendiri di port yang sama. Proses utama mem-fork ulang worker yang mati untuk menjaga ketersediaan.

Memantau Event Loop

Event loop yang tersumbat memperlambat semua koneksi. Ukur delay-nya secara rutin.

JSUkur delay event loop
const mulai = Date.now();
 
setInterval(() => {
  const delay = Date.now() - mulai;
  if (delay > 100) {
    console.warn("event loop tersumbat:", delay, "ms");
  }
  mulai = Date.now();
}, 100);

Date.now() - mulai mengukur selisih antara interval yang dijadwalkan dan yang benar-benar berjalan. Delay di atas 100 ms menandakan tugas sinkron yang terlalu berat — biasanya JSON.parse raksasa atau operasi blocking — harus dipindah ke worker thread.

Optimasi Klien

Throttle dan Virtualisasi

Klien yang hemat membuat server lebih ringan dan pengalaman lebih mulus.

JSThrottle update dari input
let lastSend = 0;
 
canvas.onmousemove = (e) => {
  const kini = Date.now();
  if (kini - lastSend < 50) return;
  lastSend = kini;
  ws.send(JSON.stringify({ type: "pointer", x: e.x, y: e.y }));
};

kini - lastSend < 50 membatasi pengiriman maksimal 20 kali per detik. Untuk daftar pesan panjang, virtual scrolling merender hanya baris yang terlihat, sehingga browser tidak membeku saat ribuan pesan masuk.

Optimasi Jaringan

TLS dan Distribusi

Jaringan yang dioptimalkan menambah latensi dari sisi infrastruktur.

  • CDN: simpan aset statis di CDN agar server hanya menangani WebSocket.
  • TLS 1.3: mengurangi jumlah round-trip handshake dibanding TLS 1.2.
  • HTTP/2 untuk handshake: mempercepat request awal sebelum upgrade.
  • Lokasi geografis: dekatkan server dengan mayoritas pengguna.

Perlu diingat: load balancer menambah satu hop. Ukur latensi end-to-end sebelum dan sesudah menambah lapisan infrastruktur.

Penutup

Episode 17 memberi kalian kacamata performa: setiap byte pesan, setiap tugas sinkron, dan setiap lapisan jaringan berpotensi menjadi bottleneck. Optimasi dimulai dari pengukuran, bukan dari tebakan.

Inti yang harus dibawa pulang:

  • Parameter TCP dan maxPayload menyetel perilaku koneksi di level rendah.
  • Minify field, kompresi, dan binary mengecilkan ukuran pesan.
  • Batching mengurangi biaya pengiriman untuk update frekuensi tinggi.
  • Cluster memanfaatkan semua inti CPU di Node.js.
  • Pantau delay event loop untuk mendeteksi tugas blocking.
  • Throttle input dan virtual scrolling membuat klien tetap responsif.

Di episode 18 berikutnya kita membahas monitoring & observability: metrik koneksi dan pesan, logging, integrasi Prometheus dan Grafana, distributed tracing dengan OpenTelemetry, serta alerting.

Belajar WebSocket - Performance Optimization | Belajar WebSocket