這個問題是一個好奇心點,作爲下面兩個程序之一工作。Perl線程中的垃圾回收
我使用Image :: Magick調整大小的照片。爲了節省一點時間,我在每個照片的自己的線程中工作,並使用信號量來限制同時工作的線程數。本來我允許每個線程一次運行,但腳本會快速爲所有照片分配3.5 GB(我只有2GB可用),並且由於所有交換到磁盤,腳本運行速度比正常情況慢5倍。
工作,信號燈版本的代碼看起來是這樣的:
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();
}
這很快分配500MB,並很好地運行,而無需以往需要更多。 (線程是加入了相反的順序提出一個觀點。)
我想知道是否有可能與同時發動80個線程,並阻止他們大多是架空的,所以我改變了我的腳本來阻塞主線程:
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();
}
該版本開始正常,但逐漸積累了原始版本使用的3.5GB空間。它比一次運行所有線程更快,但仍然比阻塞線程慢很多。
我的第一個猜測是線程所使用的內存在調用join()之前不會被釋放,並且因爲它是阻塞的主線程,所以在分配全部線程之前不會釋放線程。但是,在第一個工作版本中,線程按照或多或少的隨機順序傳遞守衛,但以相反的順序連接。如果我的猜測是正確的,那麼比任何時候四個正在運行的線程都要等待join(),這個版本也應該更慢一些。
那麼爲什麼這兩個版本如此不同呢?
接下來我要嘗試排隊。我只是好奇Perl中發生了什麼,使信號量的一個版本完美工作,而且一個工作非常糟糕。 – pconley
在您的版本中,只有解鎖sem的線程纔會使用大量內存。如果您在完成時收穫它們,那意味着在任何給定時間只有4個線程正在使用大量內存。如果你最終只收獲它們,80個線程最終會佔用大量內存。 – ikegami