JSON Toolkit

Przyspieszanie parsowania dużego JSON

Podsumowanie: Optymalizacja w złej kolejności czyni każdą wymianę biblioteki bezużyteczną. Zmierz osobno sieć, parsowanie i renderowanie, a potem ogranicz parsowania, zmniejsz ładunki i strumieniuj.

Średniozaawansowany~5 min czytaniaOpublikowano 2026-10-30Zaktualizowano 2026-10-30
Kolejność optymalizacji parsowania dużego JSON

Najważniejsze: najpierw zmierz osobno sieć, parsowanie i renderowanie — większość „wolnego parsowania” okazuje się wolnym renderowaniem — a potem wspinaj się po drabinie w kolejności: mniej parsowań, mniejsze ładunki, strumieniowanie, worker i format binarny na końcu.

Nie zaczynaj od wymiany bibliotek. Dodaj jeden timer i zwykle odkryjesz, że problemem jest renderowanie.

Krok pierwszy: zmierz etapy

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();
Dominujący etap Prawdziwy problem Poprawka
Sieć Ładunek za duży Wybór pól, paginacja, kompresja
JSON.parse Naprawdę duże wejście Mniej parsowań, strumieniowanie, worker
Renderowanie Dziesiątki tysięcy węzłów naraz Lista wirtualna, paginacja, zwijanie

Współczesne przeglądarki parsują 1 MB w około 5–15 ms, a 10 MB w 80–150 ms. Jeśli 10 MB zajmuje dwie sekundy, JSON.parse nie jest twoim wąskim gardłem.

Krok drugi: parsuj mniej

Najtańszy zysk i najbardziej przeoczony.

  • Przestań parsować ten sam ładunek wielokrotnie. Dziesięć komponentów, każdy wywołujący JSON.parse(localStorage.getItem(...)), to dziesięć parsowań. Cache’uj raz na poziomie modułu.
  • Przestań używać JSON.parse(JSON.stringify(x)) do głębokich kopii. Kosztuje więcej niż dwukrotność objętości danych; structuredClone nie.
  • Nie parsuj w wątku głównym i nie wysyłaj obiektu do workera. postMessage klonuje go ponownie. Wyślij surowy tekst i pozwól workerowi parsować.
  • Proś o mniej pól. Jeśli UI potrzebuje trzech właściwości, API nie powinno wysyłać trzystu.

Krok trzeci: zmniejsz ładunek

Paginacja przez page/size, kursory zamiast głębokiego offset, pola podsumowujące w punktach końcowych list. Zwykle bije to wszystkie optymalizacje frontendu razem, bo redukuje sieć, parsowanie i pamięć naraz.

Krok czwarty: strumieniuj

Gdy dane muszą być przetworzone jako całość i naprawdę są duże:

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);
}

Więcej kodu i brak dostępu swobodnego — pasuje tylko do przetwarzania rekord po rekordzie.

Krok piąty: przenieś poza wątek główny

Parsowanie jest szybkie, ale blokujące. Umieść je w workerze i przekazuj tekst, a nie sparsowany obiekt, inaczej klonowanie strukturalne podwaja koszt.

Krok szósty: zmień format, na końcu

Dla ruchu wewnętrznego, który konsekwentnie liczy dziesiątki megabajtów, NDJSON strumieniuje naturalnie, a Protobuf lub MessagePack są mniejsze i szybsze. Oba są zmianami protokołu wymagającymi koordynacji.

Czego nie robić

  • eval na JSON-ie: niebezpieczne i nie szybsze
  • Stringify JSON, aby osadzić go w JSON-ie: podwaja rozmiar
  • Parsowanie setek tysięcy malutkich łańcuchów w pętli: łącz je partiami

FAQ

Jak rozpoznać, czy wąskim gardłem jest parsowanie czy renderowanie?

Zmierz osobno czas żądania, odczytu tekstu, JSON.parse i renderowania przez performance.now() i traktuj największy etap jako prawdziwe wąskie gardło. Współczesne przeglądarki parsują 1 MB w około 5–15 ms, a 10 MB w 80–150 ms, więc 10-megabajtowy ładunek zajmujący dwie sekundy rzadko jest problemem JSON.parse.

Dlaczego wymiana biblioteki zwykle nie pomaga?

JSON.parse jest już natywne i szybkie; większość „wolnego parsowania” pochodzi z powtarzanego parsowania lub renderowania dziesiątek tysięcy węzłów naraz. Wymiana biblioteki kupuje 10–30%, podczas gdy usunięcie jednego pełnego parsowania często oszczędza połowę.

Czy przenieść parsowanie do Web Workera?

Przenieś je do workera, gdy parsowanie blokuje wątek główny i strona się zawiesza lub animacje gubią klatki. Przekazuj surowy tekst, a nie sparsowany obiekt, inaczej klonowanie strukturalne postMessage podwaja koszt.

Dodatkowe materiały