C’è un limite alla dimensione di una stringa in JSON con Node.js?

Una sezione della mia applicazione Node.js consiste nel ricevere una stringa come input dall’utente e memorizzarla in un file JSON. Lo stesso JSON non ha ovviamente limiti a questo, ma esiste un limite superiore alla quantità di testo che il nodo può elaborare in JSON?

Nota che non sto usando MongoDB o qualsiasi altra tecnologia per l’inserimento vero e proprio – questa è una stringa nativa e il salvataggio in un file .json usando fs .

V8 (il nodo del motore JavaScript è costruito su) fino a poco tempo fa aveva un limite rigido per la dimensione dell’heap di circa 1,9 GB .

Il nodo v0.10 è bloccato su una versione precedente di V8 (3.14) a causa della violazione delle modifiche dell’API V8 attorno ai componenti aggiuntivi nativi. Il nodo 0.12 si aggiornerà al V8 più recente (3.26), che interromperà molti moduli nativi, ma aprirà la porta per il limite di heap di 1,9 GB da sollevare.

Così com’è, un processo a nodo singolo non può contenere più di 1,9 GB di codice JavaScript, oggetti, stringhe, ecc. Combinati . Ciò significa che la lunghezza massima di una stringa è inferiore a 1,9 GB.

È ansible aggirare questo problema utilizzando il Buffer s, che memorizza i dati al di fuori dell’heap V8 (ma ancora nell’heap del processo). Una build di nodes a 64 bit può praticamente riempire tutta la tua RAM finché non hai più di 1,9 GB di dati nelle variabili JavaScript.


Detto questo, non dovresti mai avvicinarti a questo limite. Quando si tratta di molti dati, è necessario gestirli come stream. Non dovresti mai avere più di pochi megabyte (al massimo) in memoria in una volta. La buona notizia è che il nodo è particolarmente adatto per gestire i dati di streaming.

Dovresti porci alcune domande:

  • Che tipo di dati stai ricevendo dall’utente?
  • Perché vuoi memorizzarlo in formato JSON?
  • È davvero una buona idea riempire gigabyte in JSON? (La risposta è no.)
  • Cosa succederà con i dati più tardi, dopo che è stato memorizzato? Il tuo codice lo leggerà? Qualcos’altro?

La domanda che hai postato è in realtà piuttosto vaga rispetto a ciò che stai effettivamente cercando di realizzare. Per consigli più specifici, aggiorna la tua domanda con maggiori informazioni.

Se si prevede che i dati non siano mai così grandi, basta inserire un limite ragionevole di 10 MB o qualcosa sull’input, bufferizzare tutto e utilizzare JSON.stringify .

Se si prevede di trattare dati più grandi, è necessario trasmettere l’input direttamente su disco. Cerca dentro per trasformare i flussi se è necessario elaborare / modificare i dati prima che vada su disco. Ad esempio, ci sono moduli che si occupano di streaming JSON .

La dimensione massima della stringa nel nodo “vanilla” JS (v0.10.28) si trova nel ballpark di 1 GB.

Se sei di fretta, puoi testare la dimensione massima della stringa supportata con una stringa auto-raddoppiata. Il sistema testato ha 8 GB di RAM, in gran parte inutilizzati.

 x = 'x'; while (1){ x = ''+x+x; // string context console.log(x.length); } 2 4 8 16 32 64 128 256 512 1024 2048 4096 8192 16384 32768 65536 131072 262144 524288 1048576 2097152 4194304 8388608 16777216 33554432 67108864 134217728 268435456 536870912 FATAL ERROR: JS Allocation failed - process out of memory Aborted (core dumped) 

In un altro test sono arrivato a 1,000,000,000 con un char alla volta per loop.

Ora un critico potrebbe dire: “aspetta, per quanto riguarda JSON, la domanda riguarda JSON!” e vorrei gridare NON CI SONO GLI OGGETTI JSON IN JAVASCRIPT I tipi JS sono Object, Array, String, Number, ecc …. e poiché JSON è una rappresentazione String questa domanda si riduce a quella che è la stringa più lunga consentita. Ma solo per ricontrollare, aggiungiamo una chiamata JSON.stringify per indirizzare la conversione JSON.

Codice

 x = 'x'; while (1){ x = ''+x+x; // string context console.log(JSON.stringify({a:x}).length); } 

Aspettative: la dimensione della stringa JSON inizierà più di 2, perché il primo object sta andando a stringificare su “{” a “:” xx “}” per 10 caratteri. Non inizierà a raddoppiare fino a quando la stringa x nella proprietà a diventa più grande. Probabilmente fallirà intorno a 256M poiché probabilmente farà una seconda copia in stringification. Ricordare una stringificazione è indipendente dall’object originale.

Risultato:

 10 12 16 24 40 72 136 264 520 1032 2056 4104 8200 16392 32776 65544 131080 262152 524296 1048584 2097160 4194312 8388616 16777224 33554440 67108872 134217736 268435464 

Praticamente come previsto ….

Ora questi limiti sono probabilmente correlati al codice C / C ++ che implementa JS nel progetto nodeJS, che al momento credo sia lo stesso codice V8 utilizzato nei browser Chrome.

Ci sono prove da post sul blog di persone che ricompilano nodeJS per aggirare i limiti di memoria nelle versioni precedenti. Esistono anche numerosi switch della riga di comando nodejs. Non ho testato l’effetto di nulla di tutto ciò.

Questa è una buona domanda, ma penso che il limite superiore di cui devi preoccuparti non implichi la dimensione massima della stringa JSON.

A mio avviso, il limite di cui devi preoccuparti è il tempo in cui desideri bloccare il thread di richiesta mentre sta elaborando la richiesta dell’utente.

Qualsiasi dimensione di stringa superiore a 1 MB richiederà all’utente pochi secondi per il caricamento e 10 MB potrebbero richiedere minuti. Dopo aver ricevuto la richiesta, il server impiegherà alcune centinaia di millisecondi in secondi per essere analizzato in una struttura dati che porta a un’esperienza utente molto scarsa (l’analisi di JSON è molto costosa)

La larghezza di banda e i tempi di elaborazione del server oscureranno qualsiasi limite che JSON potrebbe avere sulla dimensione della stringa.