Шаблоны для много процессов PHP?

Какой шаблон разработки существуют для понимания выполнения некоторых процессов PHP и набора результатов в одном процессе PHP?

Фон:
Я действительно имею много больших деревьев (> 10 000 записей) в PHP и должен осуществить рекурсивные проверки его. Я хочу уменьшить прошедшее время выполнения.

7
задан powtac 11 June 2011 в 01:06
поделиться

6 ответов

Если ваша цель минимальна временем - решение простое для описания, но не так просто реализовать.

Вам необходимо найти шаблон, чтобы разделить работу (вы не предоставляете много информации в этом вопросе в этом отношении).

Затем используйте один основной процесс, который Forks дети, чтобы сделать работу. Как правило, общее количество процессов, которые вы используете, должны быть между N и 2n , где n - это количество сердечников.

Предполагая, что эти данные будут храниться в файлах, вы можете рассмотреть возможность использования безблокировки IO, чтобы максимизировать пропускную способность. Не делаю это, сделает большую часть вашего процесса, проводимого время в ожидании диска. PHP имеет stream_select () , который может помочь вам. Обратите внимание, что использование его не тривиально.

Если вы решите не использовать Выберите - увеличение количества процессов может помочь.


В отношении функций PCNTL функций PCNTL : я написал с ними deamon (правильный с раздумкой, изменяющий идентификатор сеанса, бегущий пользователь и т. Д. ...), и это один из самых надежных Часть программного обеспечения, которое я написал. Потому что это порождает работников для каждой задачи, даже если в одной из задач есть ошибка, она не влияет на других.

10
ответ дан 6 December 2019 в 05:48
поделиться

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

4
ответ дан 6 December 2019 в 05:48
поделиться

Из вашего скрипта PHP вы можете запустить другой скрипт (с помощью EXEC ), чтобы выполнить обработку. Сохранить обновления состояния в текстовом файле, который затем можно периодически читаться на родительской ните.

Примечание. Чтобы избежать PHP ожидания EXEC D SCRIPT D SCRIPT для завершения, труба вывода в файл:

exec('/path/to/file.php | output.log');

В качестве альтернативы вы можете вилить скрипт с помощью PCNTL Функции. Это использует один сценарий PHP, который при разложении может обнаружить, является ли он родитель или ребенок и соответственно работать. Существуют функции для отправки / приема сигналов с целью связи между родительским / ребенком, или у вас есть ребенок вход в файл, а родитель прочитал из этого файла.

Из PCNTL_FORK Страница ручной:

$pid = pcntl_fork();
if ($pid == -1) {
     die('could not fork');
} else if ($pid) {
     // we are the parent
     pcntl_wait($status); //Protect against Zombie children
} else {
     // we are the child
}
11
ответ дан 6 December 2019 в 05:48
поделиться

Используя паутину или CLI?

Если вы используете паутину, вы можете объединить эту часть в Quercus Тогда вы можете использовать преимущества многопоточности JAVA.

Я на самом деле не знаю, насколько надежен Quercus. Также я бы предложил использовать своеобразную очередь сообщений и рефакторинг кода, чтобы он не нуждался в области видимости.

Может быть, ты сможешь перестроить код на шаблон Map/Reduce. Затем вы можете запустить PHP-код в Hadoop Затем вы можете сгруппировать обработку через пару машин.

Не знаю, полезно ли это, но я наткнулся на другой проект под названием Gearman. Он также используется для кластеризации процессов PHP. Я думаю, что вы можете комбинировать это с уменьшенным скриптом, если Hadoop не тот путь, который вам нужен.

2
ответ дан 6 December 2019 в 05:48
поделиться

Вы можете использовать более эффективную структуру данных, например btree. Один раз я использовал Java, но не PHP. Вы можете попробовать этот скрипт: http://www.phpclasses.org/browse/file/708.html , это реализация btree.

Если этого недостаточно, вы можете использовать Hadoop для реализации шаблона Map / Reduce, как сказал Майкл. Я бы не стал форкнуть PHP-процесс, он, похоже, не помогает в производительности.

Лично я бы использовал PHP в качестве клиента и поместил все в Hadoop. Это руководство может помочь: http://www.lunchpauze.com/2007/10/writing-hadoop-mapreduce-program-in-php.html .

Другим решением может быть использование Java-реализации Btree: http://jdbm.sourceforge.net/ . JDBM - это объектная база данных, использующая структуры данных Btree +. Затем вы можете выполнять поиск с помощью PHP, предоставляя данные с помощью веб-службы или напрямую обращаясь к ним с помощью Quercus

3
ответ дан 6 December 2019 в 05:48
поделиться

Это:

x foreach println(_ + 1)

эквивалентно:

x.foreach(println(x$1 => x$1 + 1))

Нет никаких указаний на тип x $1 , и, честно говоря, нет смысла печатать функцию.

Очевидно, вы (для меня) намереваетесь напечатать x $0 + 1 , где x $0 будет вместо этого параметр, переданный foreach . Но давайте рассмотрим это... foreach принимает в качестве параметра Function1 [T, Unit] , где T - параметр типа списка. Вместо этого в foreach передается println (_ + 1) , которое является выражением, возвращающим Unit .

Если бы вы написали, вместо x foreach println , вы бы передали совсем другое. Вы передаете функцию (*) println , которая принимает Any и возвращает Unit , что соответствует требованиям foreach .

Это немного запутывается из-за правил расширения _ . Он расширяется до самого внутреннего разделителя выражения (скобки или фигурные скобки), за исключением тех случаев, когда они вместо параметра, и в этом случае это означает другое: приложение частичной функции.

Чтобы объяснить это лучше, посмотрите на следующие примеры:

def f(a: Int, b: Int, c: Int) = a + b + c
val g: Int => Int = f(_, 2, 3) // Partial function application
g(1)

Здесь мы применяем второй и третий аргументы к f , и вернули функцию, требующую только оставшегося аргумента. Обратите внимание, что это сработало только потому, что я указал тип g , в противном случае мне пришлось бы указать тип аргумента, который я не применял. Продолжим:

val h: Int => Int = _ + 1 // Anonymous function, expands to (x$1: Int => x$1 + 1)
val i: Int => Int = (_ + 1) // Same thing, because the parenthesis are dropped here
val j: Int => Int = 1 + (_ + 1) // doesn't work, because it expands to 1 + (x$1 => x$1 + 1), so it misses the type of `x$1`
val k: Int => Int = 1 + ((_: Int) + 1) // doesn't work, because it expands to 1 + (x$1: Int => x$1 + 1), so you are adding a function to an `Int`, but this operation doesn't exist

Давайте подробнее обсудим k , потому что это очень важный пункт. Напомним, что g является функцией Int = > Int , верно? Итак, если бы я набрала 1 + g , это имело бы смысл? Вот что было сделано в k .

Что смущает людей, так это то, что они действительно хотели:

val j: Int => Int = x$1 => 1 + (x$1 + 1)

Другими словами, они хотят, чтобы x $1 заменив _ , чтобы перейти к вне скобки, и в надлежащее место. Проблема здесь в том, что, хотя это может показаться им очевидным, что является правильным местом, это не очевидно для компилятора. Рассмотрим этот пример, например:

def findKeywords(keywords: List[String], sentence: List[String]) = sentence.filter(keywords contains _.map(_.toLowerCase))

Теперь, если бы мы расширили это до точки за скобками, мы бы получили следующее:

def findKeywords(keywords: List[String], sentence: List[String]) = (x$1, x$2) => sentence.filter(keywords contains x$1.map(x$2.toLowerCase))

Что определенно не то, чего мы хотим. Фактически, если _ не был ограничен самым внутренним ограничителем выражения, никогда нельзя было использовать _ с вложенными map , flatMap , filter и foreach .

Теперь, возвращаясь к путанице между анонимной функцией и частичным применением, смотрите здесь:

List(1,2,3,4) foreach println(_) // doesn't work
List(1,2,3,4) foreach (println(_)) // works
List(1,2,3,4) foreach (println(_ + 1)) // doesn't work

Первая строка не работает из-за того, как работает нотация операции. Scala просто видит, что println возвращает Unit , что не соответствует ожиданиям foreach .

Вторая строка работает, потому что скобки позволяют Scala оценить println (_) в целом. Это приложение частичной функции, поэтому оно возвращает значение Any = > Unit , что является приемлемым.

Третья строка не работает, поскольку _ + 1 является анонимной функцией, которую вы передаете в качестве параметра println . Вы не делаете println частью анонимной функции, что вы хотели.

Наконец, чего мало кто ожидает:

List(1,2,3,4) foreach (Console println _ + 1)

Это работает. Почему он это делает, остается в качестве упражнения для читателя.: -)

(*) На самом деле, println - это метод. При записи x foreach println метод не передается, поскольку его невозможно передать. Вместо этого Скала создаёт замыкание и пропускает его. Он расширяется следующим образом:

x.foreach(new Function1[Any,Unit] { def apply(x$1: Any): Unit = Console.println(x$1) })
-121--1174548-

Вы можете преобразовать его в байты с помощью метода encode :

>>> "insert into egg values ('egg');".encode('ascii')    # ascii is just an example
b"insert into egg values ('egg');"
-121--312666-

Вопрос кажется немного запутанным.

Я хочу уменьшить абсолютное время выполнения.

Вы имеете в виду прошедшее время? Конечно, использование правильной структуры данных улучшит пропускную способность, но для данной структуры данных минимальный порядок алгоритма является абсолютным, и не имеет ничего общего с тем, как вы реализуете алгоритм.

Какой дизайн образца существовать для реализации....

Дизайн Узоров это то, какой код является , а не шаблон для написания программ, и полезные инструменты для разработки учебного плана. Чтобы начать с образца и сделать код подходящим, он сам по себе является антипаттерном.

Никто не может ответить на этот вопрос, не зная гораздо больше о ваших данных и о том, как они структурированы, однако ключевым фактором эффективности будет структура данных, которую вы используете для реализации вашего дерева. Если прошедшее время важно, то, конечно, посмотрите на параллельное выполнение, однако, возможно, стоит рассмотреть делать операции в другом инструменте. - базы данных сильно оптимизированы для работы с большими наборами данных, однако следует отметить, что очевидный способ описания дерева в реляционной базе данных очень неэффективен, когда речь идет об изоляции субдеревьев и обходе дерева.

В ответ на предложение Адама подделать вы ответили:

Я «слышал», что pcntl не является хорошим решением. Какие-либо события?

, Где вы слышали это? Конечно, подделка из CGI или mod_php вызванного сценария - плохая идея, но ничего плохого в том, чтобы сделать это из командной строки. У вас есть google для долгих процессов PHP (предупреждайте, что там много плохой информации). Код, который вы пишете, будет варьироваться в зависимости от базовой ОС, которую вы не указали.

Я подозреваю, что вы могли бы решить большую часть ваших проблем с производительностью, определив, какие части дерева необходимо проверить, и только проверив эти части И запустив проверки при обновлении дерева, или, по крайней мере, пометив узлы как «грязные».

Вы можете найти следующие полезные:

http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/ http:/ /en.wikipedia.org/wiki/Threaded_binary_tree

C.

2
ответ дан 6 December 2019 в 05:48
поделиться
Другие вопросы по тегам:

Похожие вопросы: