ArrayBuffer-Speicherfreigabe in JavaScript beschleunigen
Der Garbage Collector von JavaScript verwaltet den Speicher automatisch, doch bei der kontinuierlichen Verarbeitung großer ArrayBuffers (mehrere MB pro Sekunde) entstehen Verzögerungen. In Browsern wie Chrome schießt der Speicherverbrauch auf Hunderte von MB in die Höhe, besonders bei Videostreaming. Firefox meistert das besser, aber Spitzen treten dennoch auf. Das ist entscheidend für 32-Bit-Prozesse und Mobilgeräte mit begrenztem RAM.
ArrayBuffer ist für Binärdaten konzipiert, bietet aber keine manuellen Freigabe- oder Größenänderungsfunktionen. Vorschläge wie ArrayBuffer.transfer() sind nicht weit verbreitet. Der detached-Zustand eines Buffers (byteLength=0, Zugriff wirft TypeError) ermöglicht es dem GC, ihn schnell zurückzugewinnen.
MessageChannel-Trick zum Abtrennen von ArrayBuffers
MessageChannel überträgt Daten zwischen Kontexten. Das Schließen von port2 trennt port1: Die Daten landen direkt beim GC, ohne auf den Event Loop zu warten.
const GarbageBin = (() => {
/** @type {MessageChannel | null} */
let messageChannel = null;
/**
* Beschleunigt die Speicherfreigabe für ArrayBuffer, TypedArray, DataView.
* @param {any} junk
*/
function dispose(junk) {
if (typeof junk === 'object' && junk) {
const buffer = junk.buffer || junk;
if (buffer.byteLength) {
if (!messageChannel) {
messageChannel = new MessageChannel();
messageChannel.port2.close();
}
messageChannel.port1.postMessage(buffer, [buffer]);
}
}
}
return { dispose };
})();
Verwendung:
let buffer = new ArrayBuffer(1_000_000);
// Arbeiten mit buffer...
GarbageBin.dispose(buffer);
buffer = null;
Kompatibilität: Funktioniert in Chrome 55+, Firefox 50+. Chrome 56 hat Probleme mit hängenden Daten. Ergebnis: Reduktion des Spitzen-Speichers um 100 MB in realen Szenarien.
Einschränkungen: Nicht für asm.js-Heaps (Firefox 49). Instabil über Versionen hinweg.
Worker-Trick für Stapelspeicherbereinigung
Worker.postMessage trennt ArrayBuffer. Das Beenden des Workers (self.close()) gibt sofort allen Thread-Speicher frei.
Optimierung: Sammle ~10 MB vor dem Herunterfahren, um Erstellungs-/Zerstörungsaufwand zu minimieren.
const GarbageBin = (() => {
const BIN_CAPACITY = 10_000_000;
/** @type {Worker | null} */
let worker = null;
let workerURL = '';
let bytesInWorker = 0;
function dispose(junk) {
if (typeof junk === 'object' && junk) {
const buffer = junk.buffer || junk;
if (buffer.byteLength) {
if (!worker) {
if (!workerURL) {
workerURL = URL.createObjectURL(new Blob([
`'use strict'; self.onmessage = ({data}) => { if (!data) self.close(); };`
], {type: 'application/javascript'}));
}
worker = new Worker(workerURL, {name: 'GarbageBin'});
}
bytesInWorker += buffer.byteLength;
worker.postMessage(buffer, [buffer]);
if (bytesInWorker > BIN_CAPACITY) {
clear();
}
}
}
}
function clear() {
if (worker) {
worker.postMessage(null);
worker = null;
bytesInWorker = 0;
}
}
return { dispose, clear };
})();
GarbageBin.clear() beim Herunterfahren aufrufen. Ergebnis: Chrome -310 MB, Firefox -70 MB Spitzen-Speicher.
Probleme: Virtuelle Adressraumauslaufen in Firefox 55+.
Leistungsvergleich und Empfehlungen
Getestet über 40 Minuten: CPU-Zyklen im Messfehlerbereich. MessageChannel langsamer als Worker in Firefox (synthetische Tests).
| Trick | Chrome-Effekt | Firefox-Effekt | Kompatibilität |
|---------------|---------------|----------------|-------------------|
| MessageChannel | -100 MB | Stabil | Gering |
| Worker | -310 MB | -70 MB | Hoch (auß. FF 55+)|
- Worker für Produktion nutzen: Zuverlässiger, größerer Effekt in Chrome.
- In Zielbrowsern testen: GC-Algorithmen entwickeln sich weiter.
- Für asm.js/WebAssembly-Heaps vermeiden.
- Mit Perfmon/Prozess-Explorer überwachen für Working Set.
Worker glänzt bei hohen Lasten (Video, Streams).
Wichtige Erkenntnisse
- Beide Tricks trennen ArrayBuffer via postMessage und beschleunigen den GC.
- Worker stapelt 10 MB, um Overhead zu reduzieren.
- Effekt: Bis zu 310 MB Spitzenreduktion bei Chrome-Streaming.
- CPU-Overhead <1% in realen Szenarien.
- Kompatibilität testen: GC-Änderungen brechen Tricks über Versionen.
— Editorial Team
Noch keine Kommentare.