JSON Toolkit

Accelerare il parsing di JSON di grandi dimensioni

In sintesi: Ottimizzare nell'ordine sbagliato rende inutile qualsiasi cambio di libreria. Misura separatamente rete, parsing e rendering, poi riduci i parsing, comprimi i payload e usa lo streaming.

Intermedio~5 min di letturaPubblicato il 2026-10-30Aggiornato il 2026-10-30
L'ordine in cui ottimizzare il parsing di JSON di grandi dimensioni

In sintesi: misura prima separatamente rete, parsing e rendering — la maggior parte del "parsing lento" si rivela rendering lento — poi sali la scala in ordine: meno parsing, payload più piccoli, streaming, un worker e un formato binario per ultimo.

Non iniziare cambiando librerie. Aggiungi un timer e di solito scoprirai che il problema è il rendering.

Passo uno: misurare le fasi

const t0 = performance.now();
const response = await fetch(url);
const text = await response.text();
const t1 = performance.now();
const data = JSON.parse(text);
const t2 = performance.now();
render(data);
const t3 = performance.now();
Fase dominante Problema reale Correzione
Rete Payload troppo grande Selezione dei campi, paginazione, compressione
JSON.parse Input davvero grande Meno parsing, streaming, worker
Rendering Decine di migliaia di nodi in una volta Lista virtuale, paginazione, compressione

I browser moderni analizzano 1 MB in circa 5–15 ms e 10 MB in 80–150 ms. Se 10 MB impiegano due secondi, JSON.parse non è il tuo collo di bottiglia.

Passo due: analizzare meno

Il guadagno più economico, e il più trascurato.

  • Smetti di analizzare ripetutamente lo stesso payload. Dieci componenti che chiamano ciascuno JSON.parse(localStorage.getItem(...)) sono dieci parsing. Metti in cache una volta a livello di modulo.
  • Smetti di usare JSON.parse(JSON.stringify(x)) per le copie profonde. Costa più del doppio del volume dei dati; structuredClone no.
  • Non analizzare sul thread principale e poi inviare l'oggetto a un worker. postMessage lo clona di nuovo. Invia il testo grezzo e lascia che il worker lo analizzi.
  • Chiedi meno campi. Se all'interfaccia servono tre proprietà, l'API non dovrebbe inviarne trecento.

Passo tre: comprimere il payload

Paginazione con page/size, cursori invece di offset profondi, campi riassuntivi negli endpoint di elenco. Questo di solito batte ogni ottimizzazione frontend combinata, perché riduce in una volta rete, parsing e memoria.

Passo quattro: streaming

Quando i dati devono essere elaborati nel loro insieme e sono davvero grandi:

import { parser } from 'stream-json';
import { streamArray } from 'stream-json/streamers/StreamArray';

const pipeline = fs.createReadStream('big.json').pipe(parser()).pipe(streamArray());
for await (const { value } of pipeline) {
  await handleOne(value);
}

Più codice, e nessun accesso casuale — adatto solo all'elaborazione record per record.

Passo cinque: spostarlo fuori dal thread principale

Il parsing è veloce ma bloccante. Mettilo in un worker e passa il testo, non l'oggetto analizzato, altrimenti la clonazione strutturata raddoppia il costo.

Passo sei: cambiare il formato, per ultimo

Per traffico interno che è costantemente nell'ordine di decine di megabyte, NDJSON si presta naturalmente allo streaming, e Protobuf o MessagePack sono più piccoli e veloci. Entrambi sono cambi di protocollo che richiedono coordinamento.

Da non fare

  • eval di JSON: non sicuro e non più veloce
  • Fare stringify di JSON per incorporarlo in JSON: raddoppia la dimensione
  • Analizzare centinaia di migliaia di minuscole stringhe in un ciclo: raggruppale

FAQ

Come capisco se il collo di bottiglia è il parsing o il rendering?

Cronometra separatamente la richiesta, la lettura del testo, JSON.parse e il rendering con performance.now(), e tratta la fase più grande come il collo di bottiglia reale. I browser moderni analizzano 1 MB in circa 5–15 ms e 10 MB in 80–150 ms, quindi un payload da 10 MB che impiega due secondi raramente è un problema di JSON.parse.

Perché cambiare libreria di solito non aiuta?

JSON.parse è già nativo e veloce; la maggior parte del "parsing lento" deriva da parsing ripetuto o dal rendering di decine di migliaia di nodi in una volta. Cambiare libreria compra il 10–30%, mentre rimuovere un parsing completo spesso risparmia metà.

Devo spostare il parsing in un Web Worker?

Spostalo in un worker quando il parsing blocca il thread principale e la pagina si blocca o le animazioni perdono frame. Passa il testo grezzo piuttosto che l'oggetto analizzato, altrimenti la clonazione strutturata di postMessage raddoppia il costo.

Ulteriori letture