Slimme strategie om met geheugen om te gaan

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • van.der.schulting
  • Registratie: Juli 2002
  • Laatst online: 09-08-2024
Ik heb een applicatie gebouwd in Ruby on Rails die de HTML scraped van meerdere sites. Elke site heeft zijn eigen scraper. Om de sites zelf zo min mogelijk te belasten zit er in een delay (sleep) in van 120 seconden tussen het ophalen van twee pagina's.
Alle scrapers lopen enkele keren per dag. Om ervoor te zorgen dat scrapers niet op elkaar hoeven te wachten, heeft elke scraper zijn eigen proces. De reden dat ik wil dat scrapers niet op elkaar hoeven te wachten is dat als een scraper zijn 'run' niet haalt voordat hij opnieuw moet gaan lopen, andere scrapers daar geen last van hebben. Met andere woorden, als voor een scraper een wachtrij ontstaat, dan hebben andere scrapers daar geen last van.

Geheugen technisch is deze oplossing loeiduur, maar volgens mij technisch wel de simpelste oplossing. Toch vraag ik me dat een beetje af...

Mijn huidige opstelling is als volgt:
Elke scraper heeft zijn eigen proces van ca. 80 MB. Bij 5 scrapers kost me dit dus al 400 MB. Door de componenten van Rails die ik niet gebruik niet in te laden win ik zo'n 40% aan geheugen. Elk proces wordt ca. 45 MB

Idealiter lijkt mij dat ik het aantal processen wat loopt moet verminderen. Ik zat zelf aan een aantal mogelijkheden te denken:
1. Stop alle scrapers die heel snel hun 'run' doen in 1 proces. Zij hebben immers toch nooit last van elkaar. Dat is een vrij makkelijke oplossing.
2. Stop alle scrapers in 1 proces en draai alle scrapers paralel in 1 proces. Dit moet volgens mij mbv paralel programmeren gebeuren. Deze oplossing lijkt mij zo idioot ingewikkeld dat het economisch gezien veel voordeliger is om dan maar enkele gigabytes RAM bij te kopen.
3. Processen alleen starten als ze ook daadwerkelijk moeten lopen... Dit heeft geen zin; nu lopen soms alle processen tegelijk.

Ik hoop dat ik het een beetje helder heb uitgelegd hoe mijn opstelling is en wat mijn probleem is.
Eigenlijk komt het erop neer dat ik het aantal processen wil verminderen, maar hoe....?
Heeft iemand een idee hoe ik het beste het aantal processen kan verminderen?
Kan ik vermijden dat door de delay (sleep) het hele proces gewoon 120 seconden stilstaat; ik kan me geen strategie bedenken om hier omheen te werken?

Acties:
  • 0 Henk 'm!

  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

Kan je niet domweg met een job-queue gaan werken? Dan kan je limiteren hoeveel job-agents/consumers je hebt en er op die manier voor zorgen dat je maximaal X aantal processen tegelijk hebt.
Dat is dus een variant die je opties allemaal combineert zonder dat je zelf moeilijk hoeft te doen mbt multi-processed/threaded te programmeren.

Als je die job-queue ook nog eens door een multi-threaded programma (geen idee hoe eenvoudig dat met RoR is) laat verwerken kan je allerlei componenten hergebruiken. Bij Java loont het bijvoorbeeld al snel om bij het type applicatie dat jij noemt Strings en andere kleine immutable objecten te "internen" (maar dan niet via String.intern()) zodat je niet met allerlei copien ervan zit.

[ Voor 14% gewijzigd door ACM op 19-03-2012 09:23 ]


Acties:
  • 0 Henk 'm!

  • Boss
  • Registratie: September 1999
  • Laatst online: 14:26

Boss

+1 Overgewaardeerd

Als één proces al 45 mb gebruikt voor iets relatiefs eenvoudigs als een beetje html parsen dan is Ruby misschien niet de beste keuze?

The process of preparing programs for a digital computer is especially attractive, not only because it can be economically and scientifically rewarding, but also because it is an aesthetic experience much like composing poetry or music.


Acties:
  • 0 Henk 'm!

Verwijderd

Boss schreef op maandag 19 maart 2012 @ 09:57:
Als één proces al 45 mb gebruikt voor iets relatiefs eenvoudigs als een beetje html parsen dan is Ruby misschien niet de beste keuze?
Misschien is het inderdaad te doen met een taal(ken ruby niet) waarbij je meerdere threads spawned en hierdoor al de meeste resources kan delen omdat je 1 instance hebt van je applicatie.

Acties:
  • 0 Henk 'm!

  • GlowMouse
  • Registratie: November 2002
  • Niet online
Alleen het downloaden kan vertragend werken, het analyzeren van de pagina's zelf zal wel snel gaan. Je kunt eraan denken om wget-processen te starten voor het downloaden, die nemen een stuk minder dan 45 MB per stuk in.

Acties:
  • 0 Henk 'm!

  • van.der.schulting
  • Registratie: Juli 2002
  • Laatst online: 09-08-2024
ACM schreef op maandag 19 maart 2012 @ 09:19:
Kan je niet domweg met een job-queue gaan werken? Dan kan je limiteren hoeveel job-agents/consumers je hebt en er op die manier voor zorgen dat je maximaal X aantal processen tegelijk hebt.
Dat is dus een variant die je opties allemaal combineert zonder dat je zelf moeilijk hoeft te doen mbt multi-processed/threaded te programmeren.
Daar zat ik ook al aan te denken, in feite mijn eerste optie, alle scrapers die een run snel genoeg draaien in dezelfde queue plaatsen.

Commando's als wget gebruiken is misschien een idee, dan kan ik nog wat extra libraries wegstrippen uit wat ik nodig heb.

Thanks voor de tips ;)

Acties:
  • 0 Henk 'm!

Verwijderd

Het overmatig geheugengebruik heeft niet met Ruby te maken, maar met de implementatie van de scraper lijkt me zo. Wat is de reden achter dit overmatig geheugengebruikt?

Hoe kleiner de overhead per thread, hoe beter. Je gebruikt nu processen om concurrency toe te passen. Wellicht is het gebruiken van threads een stuk efficienter in deze context.
Pagina: 1