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 でうまく機能し、どちらも私のニーズに非常にうまく機能しました。
はい、それは悪い考えです。その理由を説明する記事は次のとおりです: 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 モジュールを使用したい場合を除いて) 関連付けられた独自の tie マジックで変数を共有できないことを意味します。
それが悪い考えだと言うかどうかはわかりませんが、マルチスレッドを必要とする問題のドメインに対処する場合、はるかに優れたオプションがあると言えます。
私の意見では、より良い選択肢は C/C++ ですが、スキルセットとそれらの言語の経験によっては、それを書くのが難しい/時間がかかると感じるかもしれません。私のアドバイスは、Perl で記述し (質問に基づいて選択した言語であると想定しています)、それが問題になるか、パフォーマンスの問題がある場合は、そのコードを C/C++ などに移動することを検討してください。