# Webcrawler che utilizza un sacco di memoria

**URL:** <https://www.ruby-forum.com/t/webcrawler-che-utilizza-un-sacco-di-memoria/213966>\
**Category:** IT\
**Created:** [November 17, 2011, 5:12pm UTC](https://www.ruby-forum.com/t/webcrawler-che-utilizza-un-sacco-di-memoria/213966 "2011-11-17T17:12:59Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![luislavena](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/0ea827/32.png) [@luislavena](https://www.ruby-forum.com/u/luislavena)\
**Post date:** [November 17, 2011, 5:12pm UTC](https://www.ruby-forum.com/t/webcrawler-che-utilizza-un-sacco-di-memoria/213966/1 "2011-11-17T17:12:59Z")

</div>

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.

> <https://stackoverflow.com/questions/181406/ruby-memory-management>

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?

Ciao Grazie  
Luca

---

<div class="post-metadata">

**Author:** ![panthe](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/a88e4f/32.png) [@panthe](https://www.ruby-forum.com/u/panthe)\
**Post date:** [November 17, 2011, 5:22pm UTC](https://www.ruby-forum.com/t/webcrawler-che-utilizza-un-sacco-di-memoria/213966/2 "2011-11-17T17:22:01Z")

</div>

Tempo fa (molto tempo fa) ho avuto un problema simile - ma in scala  
ridotta - era Nokogiri che a causa di memory leaks mangiava pi del  
dovuto…

PS: non molto, ma spero possa aiutarti

Il 17 novembre 2011 17:12, Lucas P. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) ha scritto:

---

<div class="post-metadata">

**Author:** ![panthe](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/a88e4f/32.png) [@panthe](https://www.ruby-forum.com/u/panthe)\
**Post date:** [November 17, 2011, 5:29pm UTC](https://www.ruby-forum.com/t/webcrawler-che-utilizza-un-sacco-di-memoria/213966/3 "2011-11-17T17:29:27Z")

</div>

> 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].

Ciao  
Flavio

[1] [GitHub - ice799/memprof: A Ruby gem for memory profiling · GitHub](https://github.com/ice799/memprof)

---

<div class="post-metadata">

**Author:** ![panthe](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/a88e4f/32.png) [@panthe](https://www.ruby-forum.com/u/panthe)\
**Post date:** [November 17, 2011, 7:14pm UTC](https://www.ruby-forum.com/t/webcrawler-che-utilizza-un-sacco-di-memoria/213966/4 "2011-11-17T19:14:02Z")

</div>

2011/11/17 Lucas P. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)

> 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.

ciao,  
Luca

---

<div class="post-metadata">

**Author:** ![panthe](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/a88e4f/32.png) [@panthe](https://www.ruby-forum.com/u/panthe)\
**Post date:** [November 17, 2011, 11:06pm UTC](https://www.ruby-forum.com/t/webcrawler-che-utilizza-un-sacco-di-memoria/213966/5 "2011-11-17T23:06:10Z")

</div>

Luca M. wrote in post #1032377:

> 2011/11/17 Lucas P. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)

> 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.

Intanto grazie a tutti.  
Gentilissimi.  
Ciao  
Luca

---

<div class="post-metadata">

**Author:** ![panthe](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/a88e4f/32.png) [@panthe](https://www.ruby-forum.com/u/panthe)\
**Post date:** [November 18, 2011, 8:35am UTC](https://www.ruby-forum.com/t/webcrawler-che-utilizza-un-sacco-di-memoria/213966/6 "2011-11-18T08:35:04Z")

</div>

2011/11/17 Lucas P. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)

> 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

ciao,  
Luca

---

<div class="post-metadata">

**Author:** ![panthe](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/a88e4f/32.png) [@panthe](https://www.ruby-forum.com/u/panthe)\
**Post date:** [November 19, 2011, 3:10pm UTC](https://www.ruby-forum.com/t/webcrawler-che-utilizza-un-sacco-di-memoria/213966/7 "2011-11-19T15:10:40Z")

</div>

-----BEGIN PGP SIGNED MESSAGE-----  
Hash: SHA1

On 18/11/2011 08:34, Luca M. wrote:

> thread ma proprio a spezzare il problema in parti eseguite da _processi_  
> separati
> 
> ciao, Luca

un processo IO-bound, potresti voler essere event-driven.  
Se lo fai dovrai cambiare il modo in cui pensi:

> **[GitHub - eventmachine/eventmachine: EventMachine: fast, simple event-processing...](https://github.com/eventmachine/eventmachine)**
>
> EventMachine: fast, simple event-processing library for Ruby programs

Purtroppo per Mechanize bloccante quindi devi avere Ruby 1.9 con Fiber:

> **[Class: Fiber (Ruby 1.9.3)](http://ruby-doc.org/core-1.9.3/Fiber.html)**
>
> Class : Fiber - Ruby 1.9.3

E provare a seguire i loro consigli:  
[http://comments.gmane.org/gmane.comp.lang.ruby.modules.mechanize.user/530](http://comments.gmane.org/gmane.comp.lang.ruby.modules.mechanize.user/530)

> **[GitHub - jfairbairn/em-net-http: Monkeypatching Net::HTTP to play ball with...](https://github.com/jfairbairn/em-net-http)**
>
> Monkeypatching Net::HTTP to play ball with EventMachine.

Antonio B.  
-----BEGIN PGP SIGNATURE-----  
Version: GnuPG v1.4.11 (GNU/Linux)

iQEcBAEBAgAGBQJOx7ieAAoJELgLplTPZUF9nL4H/A1m5CfPzWD5q2aj+fgvmSXX  
ij2KxdYsZswnw0hw3OxMV8uoLi9u8lkJj/ALUyxERZi21JMKjW0tbu54U14PMbx7  
eE2/O/g/oS1njUILSPUqUdUJ+6MFexsZZoaP6CQIF+E8RE3Lx16AvtpettFOc4cI  
Sv3r27Fsck3rhgMGcJUyX8e4theShnuOFLCpkwWjV8vJHzOLqIM5mPOdJp/H2dDV  
gJ3YAPwDNFFXHFAU5KIFTStplXJrFlLae4jPhyiYpyHL16pBG9qY9tag/RMrksdQ  
fAyncb8jQbPY6n02eoD03RwL8/erBDX/IdG0nX2rASgHEzNws0NuNLbrHk1NEI4=  
=FvCb  
-----END PGP SIGNATURE-----

---

<div class="post-metadata">

**Author:** ![panthe](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/a88e4f/32.png) [@panthe](https://www.ruby-forum.com/u/panthe)\
**Post date:** [November 23, 2011, 9:42pm UTC](https://www.ruby-forum.com/t/webcrawler-che-utilizza-un-sacco-di-memoria/213966/8 "2011-11-23T21:42:27Z")

</div>

2011/11/18 Luca M. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> 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.

[1][GitHub - defunkt/resque: Moved to resque/resque · GitHub](https://github.com/defunkt/resque)

–  
twitter: @riffraff  
blog (en, it): www.riffraff.info [riffraff.blogsome.com](http://riffraff.blogsome.com)  
work: [cascaad.com](http://cascaad.com) [circleme.com](http://circleme.com)
