3

Parse::RecDescentで作成されたパーサーを使用するWebアプリケーションがあります。アプリケーションのいくつかの部分でパーサーオブジェクトが必要です。パーサーはかなりのメモリを消費するため、これまでパーサーオブジェクトをシングルトンとして扱ってきました。これは、一度に1つの式のみが同じオブジェクトによって解析されるため、純粋なCGI環境でうまく機能します。ただし、同じオブジェクトパーサーが一度に複数の文字列を解析している環境で実行している場合でも、これが機能するかどうかはわかりません。

たとえば、FastCGIでアプリケーションを実行しようとすると、2つのリクエストが同じパーサーオブジェクトを使用して異なる文字列に解析する場合に問題が発生する可能性がありますか?

必要に応じて、パーサーがシングルトンではなくなるようにアプリケーションを変更できますが、現在のソリューションの方が単純なので、使用したくありません。

4

1 に答える 1

4

私の知る限り、FastCGIはPerlスレッドではなくプロセスを使用します。したがって、あなたは安全でなければなりません。

さらに、PerlスレッドとParse :: RecDescentを使用している場合、同じオブジェクトを使用して異なるものを同時に解析することはほとんどありません。擬似コード:

use threads;
use Parse::RecDescent;
our $SingletonRD = Parse::RecDescent->new($grammar);

my @threads = map {threads->new(\&thread_loop)} (1..5);

sub thread_loop {
    $SingletonRD->parse($text);
}

これは、シングルトンの後にスレッドが作成される例です。何が起こるかです:

  • シングルトンオブジェクトを作成し、に保存し$SingletonRDます。
  • (ループで)5つのスレッドを作成します。新しいスレッドを生成するとき、perlは
    • グローバルシンボルテーブルのコピーを作成します。これには、すべてのパッケージ変数とサブルーチンが含まれます。
    • さまざまなperl-interpreter内部データ構造のコピーを作成します(OPツリーを除く)。

$SingletonRDこれにより、スレッドごとに1回ずつ効果的にクローンが作成されます。メモリが保存されていません。さて、スレッドを作成した後でのみパーサーをセットアップした場合、変数はそもそもそれらの間で共有されないので、ここでもメモリの節約スレッドの安全性はありません。

原則として、threads :: sharedを使用して、スレッド間でデータを共有できます。しかし、それはオブジェクトや複雑なネストされた構造では(簡単に)機能しません。したがって、これはParse::RecDescentパーサーの問題外になる可能性があります。

PS:Parse :: Yappかそれ以上、Parse::Eyappを見てください。それらはParse::RecDescentよりも(アルゴリズム的に)はるかに高速であり、直感的には、使用するメモリが少なくなる可能性が高いと言えます。

于 2010-02-03T19:35:03.007 に答える