Perl's Parse :: RecDescent поток безопасен? - PullRequest
3 голосов
/ 03 февраля 2010

У меня есть веб-приложение, использующее парсер, созданный с помощью Parse :: RecDescent. Объект синтаксического анализа необходим в нескольких частях приложения, и поскольку анализатор занимает довольно много памяти, я до сих пор рассматривал объект синтаксического анализа как одиночный объект. Это хорошо работает в чистой среде CGI, поскольку один и тот же объект одновременно обрабатывает только одно выражение. Однако я не уверен, будет ли это работать при работе в среде, где один и тот же анализатор объектов анализирует более одной строки одновременно.

Например, если я попытаюсь запустить приложение под FastCGI, может ли это стать проблемой, если два запроса одновременно используют один и тот же объект синтаксического анализа для анализа разных строк?

Если мне нужно, я могу изменить приложение, чтобы синтаксический анализатор больше не был единичным, однако я бы предпочел не делать этого, поскольку текущее решение проще.

1 Ответ

4 голосов
/ 03 февраля 2010

Насколько мне известно, 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.
  • Вы создаете (в цикле) пять потоков. При создании новой темы Perl делает
    • создать копию таблицы глобальных символов. Это включает в себя все переменные пакета и подпрограммы.
    • создать копию различных внутренних структур данных Perl-интерпретатора (кроме дерева OP).

Это эффективно клонирует $SingletonRD один раз для каждого потока. Память не сохранена. Теперь, если вы настроите синтаксический анализатор только после создания потоков, переменные не будут распределяться между ними с самого начала, поэтому здесь не требуется экономия памяти и , а также отсутствие безопасности потоков.

В принципе, вы можете использовать threads :: shared для обмена данными между потоками. Но это не (легко) работает с объектами и сложными вложенными структурами. Следовательно, это, вероятно, не может быть рассмотрено для парсеров Parse :: RecDescent.

PS: Посмотрите на Parse :: Yapp или еще лучше, Parse :: Eyapp. Они намного, намного быстрее (алгоритмически), чем Parse :: RecDescent, и я бы интуитивно сказал, что они даже могут использовать меньше памяти.

...