2012-12-21 25 views
8

Sto eseguendo un cron job sulla mia istanza micro Amazon EC2 ogni 12 ore. Scarica il file 118MB e lo analizza usando la libreria json. Questo ovviamente rende l'istanza a corto di memoria. La mia istanza ha 416 MB di memoria libera, ma poi eseguo lo script che scende a 6 MB e poi viene ucciso dal sistema operativo.Modo efficiente di analizzare 100 MB di carico utile JSON

Mi chiedo quali sono le mie opzioni qui? È possibile analizzare questo in modo efficiente tramite Ruby o devo scendere a roba di basso livello come C? Posso ottenere un'istanza Amazon più capace ma voglio davvero sapere se è possibile farlo tramite Ruby.

UPDATE: Ho visto yajl. Può darti oggetti json mentre analizza, ma il problema è che se il tuo file JSON contiene solo 1 oggetto root, allora sarà costretto ad analizzare TUTTO il file. Il mio JSON è simile al seguente:

--Root 
    -Obj 1 
    -Obj 2 
    -Obj 3 

Quindi, se faccio:

parser.parse(file) do |hash| 
    #do something here 
end 

Dal momento che ho solo 1 oggetto radice, si analizzerà l'intero JSON. Se Obj 1/2/3 fosse root, funzionerebbe come mi verrà dato uno per uno, ma il mio JSON non è così e analizza e mangia 500mb di memoria ...

AGGIORNAMENTO # 2: Ecco una versione più piccola del file 118mb di grandi dimensioni (7MB):

GONE

E 'da interpretare, non mi basta prendere un po' di byte fuori dal file, solo così si un vede come un'intera. La matrice che sto cercando è questo

events = json['resultsPage']['results']['event'] 

Grazie

+4

è possibile dividere il download in 6 o più segmenti e poi mettere di nuovo insieme? –

+2

100 MB di testo JSON? Cosa stai memorizzando? La biblioteca di Alessandria? ': P' –

+3

Perché stai usando JSON per questo? Non sembra il formato giusto per il lavoro. Qualcosa di più orientato alla registrazione (anche CSV) sarebbe una corrispondenza migliore. Se non riesci a controllare il formato, forse puoi rimuovere manualmente l'oggetto radice per forzare il formato in JSON orientato alla registrazione. –

risposta

6

YAJL implementa un parser streaming. Puoi usarlo per leggere il tuo JSON al volo, in modo da poter operare sui contenuti non appena arrivano, quindi scartarli (e le strutture dati generate da loro) dopo aver finito con loro. Se sei intelligente a riguardo, questo ti manterrà sotto i tuoi limiti di memoria.

Modifica: con i tuoi dati, sei veramente interessato a estrarre parti dell'oggetto JSON alla volta, piuttosto che analizzare l'intero oggetto. Questo è significativamente più complicato e richiede davvero l'implementazione del parser. I dadi e bulloni di esso sono che si desidera:

  1. passo nel eventi matrice
  2. Per ogni evento nella matrice, analizzare l'evento
  3. Passare l'evento analizzato in qualche funzione di callback
  4. Elimina l'evento analizzato e l'input sorgente per liberare memoria per l'evento successivo.

Questo non funzionerà con yajl, poiché si tratta di un oggetto qui, piuttosto che di più oggetti. Per farlo funzionare con yajl, è necessario analizzare manualmente il JSON per scoprire i limiti dell'oggetto evento, quindi passare ciascun blocco di un oggetto evento a un parser JSON per la deserializzazione. Qualcosa come Ragel potrebbe semplificare questo processo per te.

Ovviamente, sarebbe più semplice aggiornare l'istanza di AWS.

+0

Si prega di controllare il mio aggiornamento spiegando il problema che ho con yajl ... – 0xSina

+1

È possibile analizzare il JSON con sed o qualcosa per rimuovere l'oggetto radice e sostituirlo con parentesi, lasciandovi una serie di oggetti su cui operare , piuttosto che un oggetto che contiene un gruppo di array. –

+0

Se è possibile fornire i primi ~ 500 byte dell'oggetto, potremmo essere in grado di aiutare in modo più specifico. –

0

Qualcosa di simile yaji grado di analizzare il JSON come un flusso

+0

Si prega di controllare il mio aggiornamento spiegando il problema che ho avuto con yajl ... – 0xSina

Problemi correlati