I have no idea what you thought you were achieving by calling threads->tid() in your main loop?
Try this version of your code.
#!/usr/bin/perl
use strict;
use threads;
use IO::Socket;
use IO::Select;
my $thrcnt : shared = 0;
my $port = 7070;
my $socket = IO::Socket::INET->new(
LocalPort => $port,
Type => SOCK_STREAM,
Listen => SOMAXCONN,
ReuseAddr => 1
) or die "Can't create listen socket: $!";
while( my $client = $socket->accept ) {
my $thr = threads->create( \&process_request, $client );
print "\rStarting ", $thr->tid;
$thr->detach;
}
print "done: exit\n";
sub process_request {
my $socket = $_[0];
local %ENV = ();
++$thrcnt;
my $line = <$socket>;
my $ltid = threads->tid();
print "loop: $thrcnt, $ltid : $line";
close $socket;
}
__END__
Starting 9999loop: 1, 9999 : Hello:3011
Starting 10000loop: 1, 10000 : Hello:1903
Starting 10001loop: 1, 10001 : Hello:3012
Starting 10002loop: 1, 10002 : Hello:1904
I ran 4 clients that made connections, said hello and closed the socket in a tight loop until the server connections count reached 10,000. At that point the memory consumption by the server was just 7.5MB
c:\test>tasklist /fi "pid eq 10624"
Image Name PID Session Name Session# Mem Usag
+e
========================= ====== ================ ======== ===========
+=
tperl.exe 10624 0 7,676
+K
That may represent a few 100k of growth over the starting position, it's a little hard to tell as obviously starting a new thread will use extra memory. The question is whether it all gets released. Past experience shows that it does not (as of AS 5.8.6/win32 which I'm using), but the growth is not heavy in this simple case. 200k / 10,000 ~= 20 bytes per thread. Given a average machine with 1 GB of memory, it will be approximately 53 million connections before you start swapping. YMMV on other builds and OSs.
That's not to say that the leakage isn't a problem, and it can be much worse depending upon what your threads are doing, how many and what shared variables they use etc., but in order to address any serious problems of leakage, it is necessary to see the real code.
I'd also say that unless your connections are pretty long lived, starting a new thread to handle each one and throwing it away is not an efficient way to use ithreads. Perl's threads are not, by design and necessity, lightweight threads and there is a substantial amount of energy required to spawn them.
Depending upon the dynamics of your application, which is obviously not accurately represented by this test code, then there are probably better ways of structuring your application to make best use of threads.
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
|