2011-02-09 2 views
7

Possiedo un'applicazione Rails che utilizza delayed_job in una funzione di reporting per eseguire report di grandi dimensioni. Uno di questi genera un enorme file XML e può richiedere letteralmente giorni nel cattivo, vecchio modo in cui il codice viene scritto. Pensavo che, avendo visto degli ottimi benchmark su internet, Nokogiri potesse permetterci guadagni non banali in termini di prestazioni.Come posso utilizzare Nokogiri per scrivere un file XML ENORME?

Tuttavia, gli unici esempi che riesco a trovare riguardano l'utilizzo di Nokogiri Builder per creare un oggetto xml, quindi l'utilizzo di .to_xml per scrivere il tutto. Ma non c'è abbastanza memoria nel mio codice postale per gestirla per un file di queste dimensioni.

Quindi, posso utilizzare Nokogiri per eseguire lo streaming o scrivere questi dati in un file?

+3

Quanto è grande? –

+0

di solito la concatenazione di stringhe è sufficiente per molte attività di scrittura xml, evitare di costruire un albero ogni volta che è possibile ... –

+0

La concatenazione di stringhe è durata per sempre. Il vecchio builder normale sta già mostrando un miglioramento. Il file può contenere più di un gigabyte. – AKWF

risposta

4

Nokogiri è progettato per creare memoria perché si crea un DOM e lo si converte in XML al volo. È facile da usare, ma ci sono dei compromessi, e farlo in memoria è uno di questi.

Si potrebbe voler usare Erubis per generare l'XML. Anziché raccogliere tutti i dati prima dell'elaborazione e mantenere la logica in un controller, come faremmo con Rails, per risparmiare memoria è possibile inserire la logica nel modello e mantenerla iterata sui dati, il che dovrebbe aiutare con le richieste di risorse .

Se è necessario l'XML in un file che si potrebbe aver bisogno di farlo utilizzando il reindirizzamento:

erubis options templatefile.erb > xmlfile 

Questo è un esempio molto semplice, ma mostra si potrebbe facilmente definire un modello per generare XML:

<% 
asdf = (1..5).to_a 
%> 
<xml> 
    <element> 
<% asdf.each do |i| %> 
    <subelement><%= i %></subelement> 
<% end %> 
    </element> 
</xml> 

che, quando chiamo erubis test.erb uscite:

<xml> 
    <element> 
    <subelement>1</subelement> 
    <subelement>2</subelement> 
    <subelement>3</subelement> 
    <subelement>4</subelement> 
    <subelement>5</subelement> 
    </element> 
</xml> 

EDIT:

La concatenazione di stringhe stava prendendo per sempre ...

Sì, si può semplicemente a causa di garbage collection. Non viene mostrato alcun esempio di codice di come si costruiscono le stringhe, ma Ruby funziona meglio quando si utilizza << per aggiungere una stringa a un altro rispetto a quando si utilizza +.

Inoltre, potrebbe funzionare meglio non tentare di tenere tutto in una stringa, ma invece di scrivere immediatamente su disco, aggiungendo un file aperto mentre si va.

Anche in questo caso, senza esempi di codice, sto girando al buio su cosa si potrebbe fare o perché le cose scorrono lentamente.

+0

Il tuo tiro al buio è preciso, la Forza è forte con questo. Questo codice è in realtà per un report ruby ​​che risiede in lib, e ho trovato che Builder, che scrive in un oggetto io al volo, ha notevolmente migliorato le prestazioni. Grazie! – AKWF

+0

Ah. Sono contento che ci abbia aiutato. Basta non finire il disco o si avvierà all'infinito lento. –