Pobieranie wielu stron www na raz.

0

Witam,

Mój problem polega na tym, że chciałym zaoszczędzić czas (czytaj przyspieszyć algorytm), przy pobieraniu wielu stron internetowych na raz.

W czym rzecz:
Korzystam z komponentu IdHttp (pakiet INDY) i mam zamiar zparsować (wyciągnąć dane) z wielu stron internetowych w jak najkrótszym czasie.
Adresy stron zbudowane są na zasadzie:

www.strona.com/?x=wartosc1
www.strona.com/?x=wartosc2
www.strona.com/?x=wartosc3...

"wartości" mam zapisane w tablicy i odczytanie ich to nie jest problem.

Dotychczas próbowałem uruchomić jeden wątek 5 razy (z numerem kolejnym) by pracowały równolegle i parsowały stronę przy użyciu dostępnej gdzie indziej w kodzie funkcji wykorzystującej komponent IdHttp.

Pseudokod:

  Wywołanie wątków:

  twTimer.Create(0);
  twTimer.Create(1);
  twTimer.Create(2);
  twTimer.Create(3);
  twTimer.Create(4);
 Deklaracja wątku:

  TwTimer = class(TThread)
    private
      numer:integer;
      procedure SetProprties;
    protected
      procedure Execute; override;
    public
      constructor Create(numer_kolejny:integer);
  end;
  Ciało wątku:

  constructor TwTimer.Create(numer_kolejny:integer);
  begin
    inherited Create(False);
    numer:=numer_kolejny;
  end;

  procedure TwTimer.Execute;
  begin
    FreeOnTerminate := True;
    Synchronize(SetProprties);
  end;

  procedure TwTimer.SetProprties;
  var
    i:integer;
  begin

    i:=0;

{
  kazdy wątek odczytuje kolejno co piątą wartość z pamięci:
  pierwszy wątek: 0,5,10,...
  drugi: 1,6,11..
  itd.

  *ppt_count_max to maksymalna liczba, jaką może osiągnąć licznik
}
    while i*5+numer<ppt_count_max do
    begin

      get_page(tab_p[i*5+numer].wartosc);  //funkcja pobierająca stronę na podstawie "wartosci" z pamieci

    end;
  end;

#edit (na podstawie poniższego posta):
I tu jest mój problem:

Dodałem sobie na formie dodatkowy "licznik" na labelu i ilość pobranych stron idzie w tym samym tempie, co w momencie, gdybym nie stosował żadnych wątków (pobierając źródła stron zwykłą pętlą).

Nie wiem czemu mój sposób z wątkami nie przyspiesza całej tej procedury :/

Co polecacie abym wykorzystał?
Znacie może jakąś dobrą metodę / pomysł, jak pobrać wiele stron internetowych na raz?
Bałagam o pomoc ... :C

<font size="1">PS. Nie wiem czemu to się pojawia --></span> </delphi>

0

ale gdzie tu problem? coś nie działa?

0

Małę niedopowiedzenie.

Dodałem sobie na formie dodatkowy "licznik" na labelu i ilość pobranych stron idzie w tym samym tempie, co w momencie, gdybym nie stosował żadnych wątków (pobierając źródła stron zwykłą pętlą).

Nie wiem czemu mój sposób z wątkami nie przyspiesza całej tej procedury :/

0

Pewnie wynika to ze sposobu w jaki je pobierasz. Twoje komponenty sobie i tak kolejkują requesty i wykonują po kolei... ;)

0

ekhm... a nie można stworzyć obiekt klasy TIdHTTP w wątku?

0

Pewnie można :) Pytanie czy autor wątku to uczynił ;]

0

niektóre serwery wpuszczają tylko kilka requestów naraz (najczęściej dwa). inne działają na tyle powoli, że i tak nie będą w stanie generować dwóch stron w równoległych requestach szybciej, niż robią to w kolejnych (takie efekty widzę na 4programmers).

porównaj swoje rozwiązanie z tym, które przed momentem spłodziłem:
Równoległe ściąganie plików

moje będzie o tyle wydajniejsze, że jeśli co piąta (czy tam co któraś) strona będzie dłuższa, to jeden wątek nie będzie mieć więcej roboty i aplikacja nie będzie na niego czekać, bo każdy wątek po skończeniu pracy natychmiast zabiera się za kolejną wolną stronę (a nie co którąś). z drugiej strony po zakończeniu ściągania wątek się kończy i jest tworzony następny, co powoduje nieco niepotrzebnego ruchu w systemie, można to poprawić pulą wątków albo innym, lepszym zarządzaniem wątkami, ale o godzinie 2 w nocy nie chce mi się tego implementować.

0

A jak to ma chodzić szybciej jeżeli w dalszym ciągu używasz tylko jednego idHttp do pobierania stron. W każdym wątku musisz dynamicznie tworzyć nowego idHttp i przypisywać go do jednego i tego samego idCookieManager, jeżeli oczywiście używasz coookiesów.

0

gdzie masz napisane, że to tylko jeden obiekt idhttp? przecież program nie ma prawa poprawnie ściągnąć chociaż jednego pliku, jeśli wszystkie wątki będą współdzielić jeden obiekt do ściągania...

0

No jak gdzie w funkcji SetProperties, ktora jest zreszta synchronizowana, jest uzywana funkcja get_page, wiec jak przypuszczam sluzy ona do sciagania z neta, i jakos watpie zeby akurat w niej tworzony byl dynamicznie nowy idhttp i po co wtedy synchronizacja tej funkcji.

0

jak to po co - zobacz link, ktory zapodałem, tam masz używaną metodę, która jest thread-safe, a i tak jest używana synchronizacja. btw funkcja/metoda w delphi nie może być synchronizowana.
ale wracając do tematu: gdzie masz chociaż jedna linijkę, która sugeruje, że jest używany jeden obiekt idhttp? oczywiście możesz mieć rację, ale zgadujesz. poza tym w podanym kodzie akurat nie ma potrzeby robienia żadnej synchronizacji, każdy wątek ma porcję danych wydzieloną tylko dla siebie i nie będą sobie nawzajem przeszkadzać (pomijając sprawę spornej funkcji get_page).

nie ma to jak się pokłócić dla samej idei, co? :-)

1 użytkowników online, w tym zalogowanych: 0, gości: 1