🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: pl.comp.lang.perl
Article #39835

Re: perl i multithreading (dluzsze)

#39835
From: Vava
Date: Mon, 25 Oct 2004 11:50
155 lines
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.pl
References: <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