Ciao a tutti,
ho fatto uno script in Ruby 1.8 che usa le gemme mechanize, nokogiri e
open-uri e che gira sotto Linux.
Lo script è un webcrawler che raccoglie un sacco di dati aziendali
divisi in categorie. Il mio script gira perfettamente e fa quello che
deve fare ma il problema è che dopo 6-8 ore diventa enorme (1gb circa)
causando il crash del serverino che uso.
Ogni 10 risultati ottenuti li salvo in un file che al massimo raggiunge
10mb altrimenti uso un altro file svuotando il buffer relativo.
Il risultato attuale è tra le altre cose già frutto di un ottimizzazione
in quanto prima di seguire le istruzioni del post seguente soffriva di
questi problemi già dopo 4 ore.
Qualcuno potrebbe consigliarmi per ottimizzare la gestione della memoria
ottimizzando lo script? C’è un metodo serio, un IDE o qualcosa del
genere per fare un Debug efficiente?
Qualcuno potrebbe consigliarmi per ottimizzare la gestione della memoria
ottimizzando lo script? C’ un metodo serio, un IDE o qualcosa del
genere per fare un Debug efficiente?
Puoi individuare il memory leak usando memprof[1].
Lo script un webcrawler che raccoglie un sacco di dati aziendali
divisi in categorie. Il mio script gira perfettamente e fa quello che
deve fare ma il problema che dopo 6-8 ore diventa enorme (1gb circa)
causando il crash del serverino che uso.
Ogni 10 risultati ottenuti li salvo in un file che al massimo raggiunge
10mb altrimenti uso un altro file svuotando il buffer relativo.
posso rispondere con una domanda? … deve per forza essere un processo
‘monolitico’?
in casi simili quello che ho fatto e’ stato suddividere il lavoro in
unita’
piu’ piccole (e.g. ogni job fa il crawl di 10 URL) in modo che al
termine
di ogni unita di lavoro il programma che la esegue esca (liberando la
memoria.)
La divisione del lavoro in unita’ puo’ essere “statica” se sai a priori
quali sono tutte le attivita da fare (e.g. se conosci le URL da navigare
e
non segui i link interni a queste); in questo caso puoi direttamente
scrivere un programma che lancia tutti i job che ti servono. Altre volte
invece ti serve maggiore sofisticazione nella gestione delle unita di
lavoro (e.g. se non sai quante saranno in totale le URL da navigare o le
scopri strada facendo), in questi casi potresti guidare il sistema con
una
coda di lavoro in cui metti le url da navigare (mano a mano chele
scopri) e
da cui i job estraggono le url da scaricare.
posso rispondere con una domanda? … deve per forza essere un processo
‘monolitico’?
Ciao Luca e ciao a tutti gli altri,
grazie a tutti dei consigli e dei suggerimenti.
Ho provato ad utlizzare memprof come da suggerimenti ma su un Ubuntu e
su un debian dava degli errori. Però guardando come veniva utilizzato
GC.start negli esempi di utilizzo di memprof che ho trovato ho pensato
di aggiungere questa istruzione nei punti critici e ora lo script dopo
ben 7 ore di attività pesa 127MB, quasi 1/10. Quindi direi che sono
sulla buona strada, ottima direi.
Per quanto riguarda il suggerimento di Luca per il discorso dei thread
hai ragione sarebbe stata la soluzione migliore ma non sono ancora molto
pratico di Ruby e mi è riuscito più facile scrivere lo script in maniera
monolitica.
Però ora che lo sto ottimizzando potrei pensare ad implementare il tuo
suggerimento.
Per quanto riguarda il suggerimento di Luca per il discorso dei thread
hai ragione sarebbe stata la soluzione migliore ma non sono ancora molto
pratico di Ruby e mi riuscito pi facile scrivere lo script in maniera
monolitica.
eheh mi sono espresso male, io non stavo parlando di passare ad usare
dei
thread ma proprio a spezzare il problema in parti eseguite da processi
separati
thread ma proprio a spezzare il problema in parti eseguite da processi
separati
io sono con Luca, usa i processi e vivi felice
Se hai una cosa tipo
url = UrlQueue.get_next_url()
crawl_url(url)
non dovrebbe essere troppo difficile wrapparla in una funziona e
metterla dentro un fork(), ti servono solo un paio di punti di
sincronizzazione (job queue, set “in processing”).
Ma fossi in te proverei a farlo con Resque[1], che gestisce
esattamente le problematiche che hai/avrai tu (processi appesi, o che
abusano di memoria, o fetch falliti da ripetere) usando i processi e
facendoti fare davvero poco sforzo. L’unica cosa in pi installarti
redis, ma molto semplice.