2009-04-01 7 views
40

Utilizzo il modulo json in Python 2.6 per caricare e decodificare i file JSON. Tuttavia, al momento sto ottenendo prestazioni più lente del previsto. Sto usando un test case che ha una dimensione di 6 MB e che json.loads() impiega 20 secondi.Prestazioni di decodifica JSON Python

Ho pensato che il modulo json avesse un codice nativo per accelerare la decodifica?

Come si controlla se viene utilizzato?

Come confronto, ho scaricato e installato il modulo python-cjson e lo cjson.decode() impiega 1 secondo per lo stesso test case.

Preferisco utilizzare il modulo JSON fornito con Python 2.6 in modo che gli utenti del mio codice non siano tenuti ad installare moduli aggiuntivi.

(sto sviluppando su Mac OS X, ma ottenendo un risultato simile su Windows XP.)

+1

Questo è risolto in Python 2.7, per i numeri di confronto da [Tomas] (http://stackoverflow.com/users/362757/tomas), Ivo, TONy.W di seguito. Tagged this python-2.6 – smci

+0

(Per i numeri di TONy.W, l'unico problema rimasto è che stdlib json ** encode ** è ancora 2x più lento in 2.7) – smci

risposta

18

Può variare da piattaforma, ma il modulo json integrato è basato su simplejson, esclusi i speedups C. Ho trovato simplejson per essere veloce come Python-cjson comunque, quindi lo preferisco dato che ovviamente ha la stessa interfaccia del builtin.

try: 
    import simplejson as json 
except ImportError: 
    import json 

A me sembra che è il miglior linguaggio per un po ', ottenendo le prestazioni quando disponibile pur essendo compatibile in avanti.

+0

fwiw, 11nov 2009 http://pypi.python.org/packages/source/s/simplejson/simplejson-2.0.9.tar.gz su mac 10.4.11 ppc, gcc 4.2.1 => simplejson/_speedups.c: 2256: errore: ridefinizione di 'PyTypeObject PyEncoderType' ATTENZIONE: l'estensione C non può essere compilata, gli speedup non sono abilitati. – denis

+1

Se 'py-yajil' e' ultrajson' sono più veloci, qual è il vantaggio di usare 'simplejson' a parte l'aspetto di' json' ed essere puro Python? –

+0

@Shurane né 'py-yajl' né' ultrajson' supportano tutti gli argomenti che 'json' fa. 'simplejson' è più veloce di' json' (a causa degli aumenti C) e una sostituzione drop-in. –

2

Guardando nel mio installazione di Python 2.6.1 su Windows, il pacchetto json carica il modulo _json, che è integrato nel runtime. La sorgente C per il modulo json speedups è here.

>>> import _json 
>>> _json 
<module '_json' (built-in)> 
>>> print _json.__doc__ 
json speedups 
>>> dir(_json) 
['__doc__', '__name__', '__package__', 'encode_basestring_ascii', 'scanstring'] 
>>> 
+0

Ho anche pensato che JSON con _json sarebbe stato veloce. Un punto di riferimento mi ha dato torto. –

+1

Il pacchetto 'json' * usa il modulo' _json' C * sotto il cofano * già *. È poco utile accedervi direttamente. –

1

Anche se _json è disponibile, ho notato che la decodifica di json è molto lenta su CPython 2.6.6. Non ho confrontato con altre implementazioni, ma sono passato alla manipolazione delle stringhe all'interno di loop critici per le prestazioni.

24

Il nuovo Yajl - Yet Another JSON Library è molto veloce.

yajl  serialize: 0.180 deserialize: 0.182 total: 0.362 
simplejson serialize: 0.840 deserialize: 0.490 total: 1.331 
stdlib json serialize: 2.812 deserialize: 8.725 total: 11.537 

È possibile compare the libraries yourself.

Aggiornamento:UltraJSON è ancora più veloce.

+1

Grazie per il collegamento ujson;) Mi ha dato 400 req/sec in più sul mio servizio di ricerca gevent/redis. – Justin

+0

Ho provato personalmente il test e ottenuto risultati molto competitivi. Non ho avuto quasi nessun 20x di accelerazione. Utilizzando lo script di confronto (dal collegamento fornito) e il JSON di grandi dimensioni (20 MB), prestazioni ancora paragonabili. – Tomas

16

Stavo analizzando lo stesso file 10x. La dimensione del file era di 1.856.944 byte.

Python 2.6:

yajl  serialize: 0.294 deserialize: 0.334 total: 0.627 
cjson  serialize: 0.494 deserialize: 0.276 total: 0.769 
simplejson serialize: 0.554 deserialize: 0.268 total: 0.823 
stdlib json serialize: 3.917 deserialize: 17.508 total: 21.425 

Python 2.7:

yajl  serialize: 0.289 deserialize: 0.312 total: 0.601 
cjson  serialize: 0.232 deserialize: 0.254 total: 0.486 
simplejson serialize: 0.288 deserialize: 0.253 total: 0.540 
stdlib json serialize: 0.273 deserialize: 0.256 total: 0.528 

Non certo perché i numeri sono sproporzionati dai risultati. Immagino, nuove biblioteche?

+1

Notiamo anche una significativa differenza di prestazioni di stdlib (cioè built-in) json tra python 2.6 e 2.7. Quindi questo è un altro motivo per cui python 2.7 è preferito su 2.6. – RayLuo

+4

Il motivo è semplice: l'accelerazione C per json è stata aggiunta in Python 2.7. Dalle note sulla versione: "Modulo aggiornato: il modulo json è stato aggiornato alla versione 2.0.9 del pacchetto simplejson, che include un'estensione C che rende più veloce la codifica e la decodifica. "Http://docs.python.org/dev/whatsnew/2.7.html –

+2

+1 Numeri estremamente validi Tomas, quindi 2.7 corregge tutto – smci

13

un'occhiata UltraJSON https://github.com/esnme/ultrajson

qui il mio test (codice: https://gist.github.com/lightcatcher/1136415)

piattaforma: OS X 10.8.3 MBP 2.2 GHz Intel Core i7

JSON:

simplejson == 3.1.0

python-cjson == 1,0.5

jsonlib == 1.6.1

ujson == 1.30

yajl == 0.3.5

JSON Benchmark 
2.7.2 (default, Oct 11 2012, 20:14:37) 
[GCC 4.2.1 Compatible Apple Clang 4.0 (tags/Apple/clang-418.0.60)] 
----------------------------- 
ENCODING 
simplejson: 0.293394s 
cjson: 0.461517s 
ujson: 0.222278s 
jsonlib: 0.428641s 
json: 0.759091s 
yajl: 0.388836s 

DECODING 
simplejson: 0.556367s 
cjson: 0.42649s 
ujson: 0.212396s 
jsonlib: 0.265861s 
json: 0.365553s 
yajl: 0.361718s 
+1

A partire da agosto 2014, questi risultati sono per lo più accurati sulle ultime versioni di libreria. Abbiamo testato alcuni dei nostri dati casuali, e ujson leggermente (circa il 5-10%) sporge cjson che è circa x2 simplejson e 3x json. Anche le prestazioni di cjson sono abbastanza instabili su particolari insiemi di dati, quindi stiamo attaccando con ujson. –

2

Per coloro che stanno eseguendo l'analisi di uscita da una richiesta utilizzando il pacchetto di richieste, ad esempio:

res = requests.request(...) 

text = json.loads(res.text) 

Questo può essere molto lento per contenuti di risposta più grandi, ad esempio ~ 45 secondi per 6 MB sul mio MacBook 2017. Non è causato da un parser lento di json, ma da una determinazione lenta del set di caratteri da parte della chiamata res.text.

È possibile risolvere questo problema impostando il set di caratteri prima si chiedono res.text, e utilizzando il pacchetto cchardet (vedi anche here):

if res.encoding is None: 
    res.encoding = cchardet.detect(res.content)['encoding'] 

Questo rende il testo di risposta JSON parsing quasi istantanea !