Node.js Garbage Collection Tuning für Bots im 24/7 Dauerbetrieb
Node.js Garbage Collection Tuning für Bots im 24/7 Dauerbetrieb
In vielen Discord-Bot-Umgebungen führt der standardmäßige Garbage-Collection-Zyklus von Node.js zu unvorhersehbaren Verzögerungen (GC-Pauses). Wenn die V8-Engine einen vollständigen Mark-Sweep-Compact-Durchlauf startet, stoppt der JavaScript-Event-Loop für mehrere Dutzend bis Hunderte Millisekunden. Für Discord-Bots bedeutet das: verpasste Heartbeats, steigender Gateway-Ping und im schlimmsten Fall Verbindungsabbrüche mit Code 1006 (Abnormal Closure).
In diesem Guide erklären wir die V8-Speicherarchitektur und wie du Node.js mit gezielten Flags für minimale Latenz und stabilen Dauerbetrieb konfigurierst.
1. V8 Speicherarchitektur: New Space vs. Old Space
Der V8-Heap ist in zwei Hauptbereiche unterteilt:
- Young Generation (New Space):
- Hier landen alle neu erstellten Objekte (Nachrichten, Events, Strings).
- Der Bereich ist klein (typischerweise 16–64 MB) und wird extrem schnell mit dem Scavenger-Algorithmus bereinigt.
- Objekte, die zwei Scavenge-Zyklen überleben, werden in den Old Space befördert.
- Old Generation (Old Space):
- Enthält langlebige Objekte (Bot-Client, Modul-Singletons, Langzeit-Caches).
- Die Bereinigung erfordert teure Mark-Sweep- und Mark-Compact-Zyklen, die Stop-the-World Pausen verursachen.
┌────────────────────────────────────────────────────────┐
│ V8 Process Memory │
├──────────────────────────┬─────────────────────────────┤
│ New Space (16-64 MB) │ Old Space (up to max-old) │
│ ┌────────────┬────────┐ │ ┌───────────────────────┐ │
│ │ Semi-Space │ To- │ │ │ Long-Lived Objects │ │
│ │ From-Space │ Space │ │ │ Bot Client, Caches │ │
│ └────────────┴────────┘ │ └───────────────────────┘ │
│ [Scavenge GC] │ [Mark-Sweep-Compact] │
└──────────────────────────┴─────────────────────────────┘
2. Die wichtigsten V8 Flags für Discord-Bots
Beim Start deines Node.js-Prozesses kannst du das Verhalten des Garbage Collectors über Runtime-Flags steuern:
A. Heap-Limit explizit setzen: --max-old-space-size
Standardmäßig allokiert Node.js auf 64-Bit-Systemen bis zu 2 oder 4 GB Speicher, bevor aggressiv aufgeräumt wird. Für Bots führt dies dazu, dass Müll lange im RAM verbleibt:
# Auf einem Server mit 1 GB RAM-Zuweisung:
node --max-old-space-size=512 dist/index.js
Effekt: V8 startet Aufräumzyklen deutlich früher, bevor das System in Swap-Memory gerät oder der Linux OOM-Killer den Prozess terminiert.
B. Inkrementelles & Paralleles Marking: --max-semi-space-size
Vergrößert den New-Space, sodass kurzlebige Objekte (wie Payload-Parsing von Discord-Nachrichten) komplett im schnellen New-Space abgeräumt werden, ohne jemals in den Old-Space zu wandern:
node --max-semi-space-size=64 --max-old-space-size=512 dist/index.js
3. GC-Metriken im laufenden Betrieb protokollieren
Mit dem nativen perf_hooks-Modul von Node.js kannst du die genaue Dauer jeder GC-Pause in Mikrosekunden messen:
import { PerformanceObserver } from 'node:perf_hooks';
export function setupGCMonitoring() {
const obs = new PerformanceObserver((list) => {
const entries = list.getEntries();
for (const entry of entries) {
const durationMs = entry.duration;
// entry.detail enthält den GC-Typ: 1 = Scavenge, 2 = Mark-Sweep-Compact, 4 = Incremental
if (durationMs > 25) {
console.warn(`[GC Warning] Lange GC-Pause erkannt: ${durationMs.toFixed(2)} ms (Typ: ${entry.name})`);
}
}
});
obs.observe({ entryTypes: ['gc'] });
}
Wenn du in den Logs regelmäßige Spitzen von über 50 ms siehst, bedeutet dies, dass zu viele temporäre Objekte in den Old Space befördert werden.
4. Empfohlene Produktions-Startparameter
Für Container- und Cloud-Deployments auf KiroCloud empfehlen wir folgende Kombination im package.json Startskript:
{
"scripts": {
"start:prod": "node --max-semi-space-size=64 --max-old-space-size=768 --enable-source-maps dist/index.js"
}
}
--max-semi-space-size=64: Hält JSON-WebSocket-Payloads im schnellen Young-Space.--max-old-space-size=768: Verhindert, dass der Prozess das 1-GB-Containerlimit überschreitet.--enable-source-maps: Präzise Stack-Traces bei Fehlern ohne Performance-Verlust.
Luca Lichtenwald
Spezialisiert auf hochverfügbare Discord-Bot-Infrastrukturen, V8-Memory-Tuning und kryptografische Zero-Trust-Architekturen.