Is it a bad idea to write multithreaded programs (specifically, TCP server daemons) in Perl?
I don't know that I would say it's a bad idea, but I would say there are much better options when dealing with problem domains requiring multi-threading.
A better option in my opinion would be C/C++, but depending on your skill-set and you're experience with those languages, you may find it difficult/time consuming to write it. My advice would be to write it in Perl (I'm assuming that is your language of choice based on the question) and if it becomes a problem or you have performance issues then look into moving that code over to something like C/C++.
It depends on the version of Perl you are using and the operating system you are on. See Bugs and Limitations in perldoc threads
.
Go ahead and write your server in Perl using ithreads. If it becomes a burden to duplicate the interpreter, your initial implementation serves as a prototype, and you will be able to translate your application logic easily into C, say. See perldoc perlthrtut
.
Perl is a great language for a server. If you come to any areas where interpreted code is bogging down the application, you can write extension code in C to handle it.
You might also look at non-blocking I/O to avoid the overhead of threads. IO::Lambda is a nice module for that, simplifying event-based programming to a few [anonymous] subroutines.
Yes, it is a bad idea. Here is an article describing why it is so: Things you need to know before programming Perl ithreads
Here's just an excerpt from the aforementioned post:
Unlike most other threads implementations that exist in the world, including the older perl 5.005 threads implementation, variables are by default not shared between Perl ithreads. So what does that mean? It means that every time you start a thread all data structures are copied to the new thread. And when I say all, I mean all. This e.g. includes package stashes, global variables, lexicals in scope. Everything! An example:
use threads ();
my $foo;
threads->new( sub {print "thread: coderef = ".\$foo."\n"} )->join;
print " main: coderef = ".\$foo."\n";
which prints this on my system:
thread: coderef = SCALAR(0x1eefb4)
main: coderef = SCALAR(0x107c90)
But wait, you might say, shared variables may be a lot better. So why don't I make all variables shared in my application so I won't suffer from this. Well, that is wrong. Why? Because shared variables in fact aren't shared at all. Shared variables are in fact ordinary tied variables (with all the caveats and performance issues associated with tied variables) that have some "magic" applied to them. So, not only do shared variables take up the same amount of memory as "normal" variables, they take up extra memory because all of the tied magic associated with it. This also means that you cannot have shared variables with your own tie-magic associated with it (unless you want to use my Thread::Tie module).
I'd write such a thing in with POE, and then let POE::Wheel::Run fork off separate processes as needed.
Although, it's possible, I wouldn't do it. You can't do pre-spawning of threads, since you can't pass a new socket to existing threads.
Thread creation on a as needed basis can be very expensive, since all data structures are copied, for every new thread. With a simple program, that's okay, but if you loaded a a lot of stuff in memory first, it's prohibitive.
Because of this, I have used POE and AnyEvent, in separate project, when I needed a network server. They are not threaded, but at least you can handle multiple connection in a somewhat sane way. They work well on Windows and Linux, and both worked really well for my needs.