Redis
 sql >> Database >  >> NoSQL >> Redis

La decodifica Go JSON è molto lenta. Quale sarebbe un modo migliore per farlo?

L'analisi di dati JSON di grandi dimensioni sembra essere più lenta di quanto dovrebbe essere. Varrebbe la pena individuare la causa e inviare una patch agli autori di Go.

Nel frattempo, se puoi evitare JSON e utilizzare un formato binario, non solo eviterai questo problema; guadagnerai anche il tempo che il tuo codice sta dedicando all'analisi delle rappresentazioni decimali ASCII dei numeri nei loro equivalenti binari IEEE 754 (e possibilmente introducendo errori di arrotondamento mentre lo fai.)

Se sia il mittente che il destinatario sono scritti in Go, ti suggerisco di utilizzare il formato binario di Go:gob .

Facendo un rapido test, generando una mappa con 2000 voci, ciascuna una fetta con 1050 semplici float, mi dà 20 MB di JSON, che impiegano 1,16 secondi per l'analisi sulla mia macchina.

Per questi rapidi benchmark, prendo il meglio di tre esecuzioni, ma mi assicuro di misurare solo il tempo di analisi effettivo, con t0 := time.Now() prima della chiamata Unmarshal e stampando time.Now().Sub(t0) dopo.

Utilizzando GOB, la stessa mappa genera 18 MB di dati, che impiegano 115 ms per l'analisi:
un decimo del tempo .

I tuoi risultati varieranno a seconda di quanti float effettivi hai lì. Se i tuoi float hanno molte cifre significative, meritando la loro rappresentazione float64, allora 20 MB di JSON conterranno molto meno dei miei due milioni di float. In tal caso la differenza tra JSON e GOB sarà sempre più netta.

A proposito, questo dimostra che il problema risiede effettivamente nel parser JSON, non nella quantità di dati da analizzare, né nelle strutture di memoria da creare (perché entrambi i test stanno analizzando ~ 20 MB di dati e ricreando le stesse fette di float). La sostituzione di tutti i float con le stringhe nel JSON mi dà un tempo di analisi di 1,02 sec, confermando che la conversione dalla rappresentazione di stringhe ai float binari richiede un certo tempo (rispetto al solo spostamento di byte in giro) ma non è il principale colpevole.

Se il mittente e il parser non sono entrambi Go, o se si desidera ridurre ulteriormente le prestazioni rispetto a GOB, è necessario utilizzare il proprio formato binario personalizzato, utilizzando i buffer di protocollo o manualmente con "encoding/binary" e amici.