To pytanie jest ciekawostką, ponieważ jeden z dwóch programów poniżej działa.Usuwanie śmieci w wątkach Perla
Używam Image :: Magick do zmiany rozmiaru kilku zdjęć. Aby zaoszczędzić trochę czasu, pracuję nad każdym zdjęciem we własnym wątku i używam semafora, aby ograniczyć liczbę działających jednocześnie wątków. Początkowo zezwalałem na uruchamianie wszystkich wątków naraz, ale skrypt szybko przydzieliłby 3,5 GB dla wszystkich zdjęć (mam tylko 2 GB dostępne), a skrypt byłby 5 razy wolniejszy niż zwykle z powodu zamiany na dysk.
Działanie, semafor kod wersja wygląda tak:
use threads;
use Thread::Semaphore;
use Image::Magick;
my $s = Thread::Semaphore->new(4);
foreach (@photos) {
threads->create(\&launch_thread, $s);
}
foreach my $thr (reverse threads->list()) {
$thr->join();
}
sub launch_thread {
my $s = shift;
$s->down();
my $image = Image::Magick->new();
# do memory-heavy work here
$s->up();
}
Ten szybko przydziela 500MB i działa całkiem dobrze, nigdy nie wymagając więcej. (Nitki są połączone w kolejności odwrotnej do punktu).
Zastanawiałam się, czy może istnieć napowietrznych z uruchomieniem 80 wątków jednocześnie blokując większość z nich, więc zmienił mój skrypt do blokowania główny wątek:
my $s = Thread::Semaphore->new(4);
foreach (@photos) {
$s->down();
threads->create(\&launch_thread, $s);
}
foreach my $thr (threads->list()) {
$thr->join();
}
sub launch_thread {
my $s = shift;
my $image = Image::Magick->new();
# do memory-heavy work here
$s->up();
}
Ta wersja zaczyna się dobrze, ale stopniowo gromadzi 3,5 GB miejsca w oryginalnej wersji. Jest szybszy niż uruchamianie wszystkich wątków naraz, ale wciąż jest nieco wolniejszy od blokowania wątków.
Moim pierwszym przypuszczeniem było to, że pamięć używana przez wątek nie jest zwalniana, dopóki nie zostanie wywołana funkcja join(), a ponieważ jest ona głównym wątkiem blokującym, żadne wątki nie są zwalniane, dopóki wszystkie nie zostaną przydzielone. Jednak w pierwszej, działającej wersji wątki przekazują strażnikowi w bardziej przypadkowej kolejności, ale dołączają w odwrotnej kolejności. Jeśli moje przypuszczenie jest poprawne, wówczas wiele więcej niż cztery uruchomione wątki powinny w każdej chwili czekać na join() ed, a także ta wersja powinna być wolniejsza.
Dlaczego te dwie wersje są tak różne?
Zamierzałem spróbować kolejki w następnej kolejności. Jestem ciekawy, co się dzieje w Perlu, który sprawia, że jedna wersja semafora działa doskonale, a jedna działa okropnie. – pconley
W twojej wersji tylko wątki, które odblokowały sem, zużywają dużo pamięci. Jeśli zbierzesz je w trakcie, oznacza to, że tylko 4 wątki zużywają dużo pamięci w danym momencie. Jeśli zbierzesz je tylko na końcu, 80 wątków ostatecznie zużyje dużo pamięci. – ikegami