在 Perl 中编写多线程程序(特别是 TCP 服务器守护进程)是不是一个坏主意?
7 回答
Perl 是一种很棒的服务器语言。如果您遇到解释代码使应用程序陷入困境的任何领域,您可以用 C 编写扩展代码来处理它。
您还可以查看非阻塞 I/O 以避免线程开销。IO::Lambda 是一个很好的模块,它将基于事件的编程简化为几个 [匿名] 子例程。
这取决于您使用的 Perl 版本和您所在的操作系统。请参阅中的错误和限制。perldoc threads
我会用POE写这样的东西,然后让POE::Wheel::Run根据需要分叉不同的进程。
继续并使用 ithreads 在 Perl 中编写您的服务器。如果复制解释器成为负担,您的初始实现将用作原型,并且您将能够轻松地将应用程序逻辑转换为 C,例如。见perldoc perlthrtut
。
虽然有可能,但我不会这样做。您无法预先生成线程,因为您无法将新套接字传递给现有线程。
在需要的基础上创建线程可能非常昂贵,因为对于每个新线程都复制了所有数据结构。用一个简单的程序,没关系,但是如果你先在内存中加载了很多东西,那就令人望而却步了。
因此,当我需要网络服务器时,我在单独的项目中使用了 POE 和 AnyEvent。它们不是线程的,但至少您可以以某种理智的方式处理多个连接。它们在 Windows 和 Linux 上运行良好,并且都非常适合我的需求。
我不知道我会说这是一个坏主意,但我会说在处理需要多线程的问题域时有更好的选择。
在我看来,更好的选择是 C/C++,但根据您的技能组合和您对这些语言的经验,您可能会发现编写它很困难/很耗时。我的建议是用 Perl 编写它(我假设这是您根据问题选择的语言),如果它成为一个问题或者您有性能问题,那么考虑将该代码移至 C/C++ 之类的东西。
是的,这是个坏主意。这是一篇描述为什么会这样的文章:Things you need to know before programming Perl ithreads
这里只是上述帖子的摘录:
与世界上存在的大多数其他线程实现不同,包括旧的 perl 5.005 线程实现,变量默认情况下不在 Perl ithreads 之间共享。那是什么意思?这意味着每次启动线程时,所有数据结构都会复制到新线程。当我说全部时,我的意思是全部。这例如包括包存储、全局变量、范围内的词法。一切!一个例子:
use threads ();
my $foo;
threads->new( sub {print "thread: coderef = ".\$foo."\n"} )->join;
print " main: coderef = ".\$foo."\n";
在我的系统上打印:
thread: coderef = SCALAR(0x1eefb4)
main: coderef = SCALAR(0x107c90)
但是等等,你可能会说,共享变量可能要好得多。那么为什么我不在我的应用程序中共享所有变量,这样我就不会受此影响。好吧,那是错误的。为什么?因为共享变量实际上根本不共享。共享变量实际上是普通的绑定变量(具有与绑定变量相关的所有警告和性能问题),它们具有一些“魔法”。因此,共享变量不仅占用与“普通”变量相同的内存量,而且还占用了额外的内存,因为所有与之相关的绑定魔法。这也意味着您不能将共享变量与您自己的关联魔法关联起来(除非您想使用我的 Thread::Tie 模块)。