Article View: pl.comp.lang.perl
Article #39835Re: perl i multithreading (dluzsze)
From: Vava
Date: Mon, 25 Oct 2004 11:50
Date: Mon, 25 Oct 2004 11:50
155 lines
6570 bytes
6570 bytes
misiu <a@polbox.com> wrote:
> ogolnie moze opisze troszke dokladniej sytuacje: do napisania jest demon
> ktory bedzie nasluchiwal na kilku socketach jednoczesnie i bedzie
> otrzymywal DUZO zapytan, kazde z nich realizuje wzglednie prosta funkcje
> ktora konczy sie zmiana jednej-dwoch wartosci w omawianym glownym hashu.
> funkcje oczywiscie same wiedza dokladnie gdzie i ktora wartosc zmienic
> zeby nie bylo potrzeby przeszukiwania
>
> z tego co widze aby uzywac modulu storable musialbym w kazdym procesie
> potomnym "odserializowac" cala strukture co chyba nie bedzie optymalne
> pod wzgledem wydajnosci biorac pod uwage fakt ze dziecko zyje bardo
> krotko i nie zmienia za duzo.
To ja bym to w ogóle inaczej zrobił - zamiast serwera wątkującego, czy
forkującego - multiplekser.
Skoro każde połączenie to chwilka, to może to być najwydajniejsze
rozwiązanie - dobrze się to sprawdza w serwerach typu chat.
Kilka przykładów jest w świetnej książce "Perl - tworzenie aplikacji
sieciowych" - głównie polega na zrobieniu tabeli połączeń i przełączaniu
się select'em - tylko trzeba pamiętać o uzyciu nieblokujących IO...
Ewentualnie inaczej - z wykorzystaniem serwera wątkującego - coś w stylu:
#!perl
use strict;
use threads;
use thread::shared;
use Thread::Queue;
my $queue = new Thread::Queue; # tworzymy kolejke
my $QUIT : shared = 0;
my $struktura = {ABC => [123,234,345], DEF => {bleble => 100, zzzz => 34}}; #
nasza struktura
$SIG{INT}=$SIG{TERM}=\&SWEEP; # obsluga sygnalow zamkniecia aplikacji
my @ports = qw/666 667 668/; # przykładowe porty, na których nasłuchujemy
foreach my $port (@ports) {
threads->create("main", $port); # tworzymy wątek serwera
}
while(!QUIT){ # główna pętla programu
if $queue->pending;
while(!QUIT && (my $dana = $queue->dequeue_nb)){ # czytamy z kolejki
# przetwarzamy toto...
my ($id, $wart) = split ":",$dana;
if ($id eq 'bleble') { # no i wrzucenie we właściwe miejsce struktury,
zależnie od $id
$struktura->{DEF}->{bleble} = $wart;
} elsif ($id eq ABC) {
push @{$struktura->{ABC}}, $dana;
}
threads->yield;
}
sleep 1; # coby nie blokować 100% procesora, jak nie ma nic w kolejce
}
sub main { # obsługuje nasłuchiwanie na danym porcie i rozdziela połączenia do
wątków potomnych
my $port = shift;
my $sck = IO::Socket::INET->new(Port => $port, ...); # tworzenie socketa
while(!$QUIT && $conn=$sck->accept) { # trzeba ustawić rozsądny timeout
threads->create("obsluga", $conn); # tworzymy wątek do obsługi
połączenia
... # tutaj obsaługujemy wątki potomne, jakiś join, czy coś w tym stylu...
}
}
sub obsluga { # obsluga pojedynczego polaczenia
# czytamy dane z socketa
# i przetwarzamy je
my $wart = ...; # jakaś wyliczona wartosc
my $id = 'bleble'; #Coś, po czym można zidentyfikować, gdzie wrzucić
wartość
$queue->enqueue("$id:$wart"); #Wrzucamy to do kolejki
}
sub SWEEP { # czyszczenie po watkach
QUIT:{ # zasieg dla lock
lock($QUIT); # blokujemy
$QUIT=1; # ustawiamy jako prawda
}
threads->yield(); # oddajemy sterowanie
for(threads->list()){ # dla kazdego watku
$_->join(); # zbieramy zniwa
threads->yield(); # oddajemy sterowanie
}
}
__END__
Oczywiście to szkielet - trza to rozbudować o nieblokujące IO, detekcję błędów,
demonizację
skryptu, zabezpieczenia (chroot, etc.) i podobne rzeczy - to tylko koncepcja
modelu
rozwiązania...
IMVHO to dość dobrze się sprawdzi - jak za mało wydajne, to można zrobić
prethreading
i bawić się pulą wątków dla każdego portu.
Ale sądzę, że multiplekser byłby wydajniejszy (nie ma narzutu na tworzenie i
żniwa
po wątkach).
Można połączyć multiplekser z wątkami - czyli dla każdego portu zrobić podwątek
(main()
w powyższym przykładzie), a w ramach takiego wątku multipleksować połączenia...
Fakt - serwery multipleksujące sa najbardzie skomplikowane jak chodzi o ich
pisanie - trzeba
wielu rzeczy pilnować. Ale w sytuacjach, gdzie połączenie ma niewiele do roboty,
a połączeń
jest dużo, to jest to najwydajninejsze rozwiązanie...
ja podobne coś wykorzystałem do zrobienia rozszerzenia narzędzia IBM Rational
Team Test - takie
coś do testów obciążeniowych. Toto tworzy kilka tysięcy wirtualnych użytkowników
i męczy jakiś
serwer. Jednak wbudowane logowanie jest po pierwsze słabo konfigurowalne i
ubogie,
a po drugie - tworzy lokalne logi, z których ściąganiem i obróbką są problemy
(test jest rozproszony
na kilkudziesięciu komputerach).
Jako, że VU mogą słać dowolne rzeczy na socket, to dorobiłem wysyłanie krótkich
(coby nie spowalniać
testów) informacji na serwer.
A serwer to właśnie takie twórcze połączenie wielowątkowości i multipleksera -
dla każdego komputera
z farmy oddzielny wątek. Watki wrzucają dane do kolejki a oddzielny wątek wrzuca
to sukcesywnie
do logu (wydajność tego wątku nie jest kluczowa). Przy 3000 VU serwer otrzymuje
jakieś 6-9tys
tysięcy krótkich (max. 256 znaków) komunikatów na sekundę i się wyrabia bez
problemu...
> pozatym z tego co wyczytalem w necie to jakiekolwiek wykorzystywanie IPC
> z system V ciagnie za soba spora utrate wydajnosci. nie wiem czy to
> prawda? nie wspomne o tym ze niejednokrotnie spotkalem sie z opisem
> threadow w perlu jako "highly experimental" :)
W wersjach niższych niż 5.8 - tak ;-)
Pozdrawiam
--
Vava
Wawrzyniec Żurowski
Victoria vale, et ubique es, suaviter sternutas
--
Wysłano z serwisu OnetNiusy: http://niusy.onet.pl
Technical Details
Message-ID:
<2d43.00000134.417ce883@newsgate.onet.pl>Path:
mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!newsfeed.gazeta.pl!news.onet.pl!newsgate.onet.pl!niusy.onet.plReferences:
<clh1r1$kj3$1@kujawiak.man.lodz.pl>Show Full Headers
Complete Article Headers
Path: mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!newsfeed.gazeta.pl!news.onet.pl!newsgate.onet.pl!niusy.onet.pl From: "Vava" <rosomakolakWYTNIJTO@poczta.onet.pl> Newsgroups: pl.comp.lang.perl Subject: Re: perl i multithreading (dluzsze) Date: 25 Oct 2004 13:50:28 +0200 Organization: Onet.pl SA Lines: 155 Message-ID: <2d43.00000134.417ce883@newsgate.onet.pl> References: <clh1r1$kj3$1@kujawiak.man.lodz.pl> NNTP-Posting-Host: newsgate.onet.pl Mime-Version: 1.0 X-Trace: newsgate.test.onet.pl 1098705028 24398 213.180.130.18 (25 Oct 2004 11:50:28 GMT) X-Complaints-To: abuse@onet.pl NNTP-Posting-Date: 25 Oct 2004 11:50:28 GMT X-Mailer: http://niusy.onet.pl X-Forwarded-For: 212.2.96.150, 192.168.243.35 X-User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Opera 7.20 [pl] Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit