Какой шаблон дизайна существует для реализации выполнения некоторых процессов PHP и сбора результатов в одном PHP-процессе?
Задний план:
У меня есть много больших деревьев (> 10000 записей) на PHP и им приходится выполнять рекурсивные проверки. Я хочу сократить время выполнения.
Если ваша цель – минимальное время – решение просто описать, но не так просто реализовать.
Вам нужно найти образец для разделения работы (вы не предоставляете много информации в вопросе в этом отношении).
Затем используйте один мастер-процесс, который позволяет детям выполнять работу. Как правило, общее количество используемых вами процессов должно быть между n
и 2n
, где n
– количество ядер, которые имеет машина.
Предполагая, что эти данные будут сохранены в файлах, вы можете использовать неблокирующий IO, чтобы максимизировать пропускную способность. Не делая этого, большая часть вашего процесса будет тратить время на ожидание диска. PHP имеет stream_select()
который может вам помочь. Обратите внимание, что использование его не является тривиальным.
Если вы решите не использовать select
– увеличение количества процессов может помочь.
Что касается функций pcntl
: я написал с ними deamon (подходящий для разметки, изменения идентификатора сеанса, работающего пользователя и т. Д.), И это одно из самых надежных программных продуктов, которые я написал. Поскольку он порождает рабочих для каждой задачи, даже если в одной из задач есть ошибка, это не влияет на других.
С вашего php-скрипта вы можете запустить другой скрипт (используя exec
) для выполнения обработки. Сохраните обновления статуса в текстовом файле, который затем может быть периодически прочитан родительским потоком.
Примечание: чтобы PHP не дождался завершения сценария exec'd, подключите вывод к файлу:
exec('/path/to/file.php | output.log');
Кроме того , вы можете разблокировать скрипт, используя функции PCNTL . Это использует один php-скрипт, который, когда forked может определить, является ли он родителем или дочерним, и работает соответствующим образом. Существуют функции для отправки / получения сигналов для связи между родителем / дочерним элементом или у вас есть дочерний журнал для файла, а родительский – это чтение из этого файла.
На странице руководства 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 }
Это может быть подходящее время, чтобы рассмотреть возможность использования очереди сообщений , даже если вы запустите ее на одной машине.
Вы можете использовать более эффективную структуру данных, такую как btree. Я использовал один раз в Java, но не в PHP. Вы можете попробовать этот скрипт: http://www.phpclasses.org/browse/file/708.html , это реализация btree.
Если этого недостаточно, вы можете использовать Hadoop для реализации схемы Map / Reduce, как сказал Майкл. Я бы не стал видоизменять PHP-процесс, он, похоже, не помогает для performace.
Лично я бы использовал 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
Вопрос, похоже, немного запутан.
Я хочу уменьшить абсолютное время выполнения.
Вы имеете в виду прошедшее время? Разумеется, использование правильной структуры данных улучшит пропускную способность, но для данной структуры данных минимальный порядок алгоритма является абсолютным и не имеет никакого отношения к тому, как вы реализуете алгоритм.
Какой шаблон дизайна существует для реализации ….?
Шаблоны проектирования – это код, а не шаблон для написания программ и полезные инструменты для разработки учебной программы. Чтобы начать с шаблона и сделать свой код подходящим, он сам по себе является анти-шаблоном.
Никто не может ответить на этот вопрос, не зная намного больше о ваших данных и о том, как его структурировать, однако ключевым фактором эффективности будет структура данных, которую вы используете для реализации вашего дерева. Если прошедшее время имеет важное значение, то обязательно посмотрите на параллельное выполнение, однако также стоит рассмотреть возможность выполнения операции в другом инструменте – базы данных сильно оптимизированы для работы с большими наборами данных, однако обратите внимание, что очевидный метод описания дерева в реляционная база данных очень неэффективна, когда дело касается изоляции поддерев и ходьбы по дереву.
В ответ на предложение Адама о разветвлении вы ответили:
Я «слышал», что pcntl не является хорошим решением. Любой опыт?
где ты услышал это? Конечно, разворачивание из сценария CGI или mod_php – это плохая идея, но ничего не получается сделать из командной строки. У вас есть google для длительных PHP-процессов (будьте осторожны, там много плохой информации). Код, который вы пишете, будет зависеть от базовой ОС, о которой вы не указали.
Я подозреваю, что вы можете решить большую часть проблем с производительностью, указав, какие части дерева нужно проверять, и только проверять эти части и запускать проверки при обновлении дерева или, по крайней мере, маркировать узлы как «грязные».
Вы можете найти их полезными:
http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/ http://en.wikipedia.org/wiki/Threaded_binary_tree
C.
Использование веб-интерфейса или CLI?
Если вы используете веб, вы можете перевести эту часть в Quercus. Тогда вы можете использовать преимущества многопоточности JAVA.
Я действительно не знаю, насколько надежным является Quercus. Я также предлагаю использовать очередь сообщений и рефакторинг кода, поэтому он не нуждается в области.
Возможно, вы можете перестроить код на шаблон Map / Reduce. Затем вы можете запустить PHP-код в Hadoop. Затем вы можете скопировать обработку через пару машин.
Я не знаю, полезно ли это, но я наткнулся на другой проект под названием Gearman . Он также используется для кластеризации процессов PHP. Я думаю, вы можете комбинировать это с сценарием сокращения, если Hadoop не так, как вы хотите.
Существует довольно новое (с 2012 года) расширение PHP: pthreads . Он может быть установлен через PECL .
Простая реализация в PHP-коде: распространяется от класса Thread
. Добавьте метод run()
и выполните метод start()
.
<?php // Example from http://www.phpgangsta.de/richtige-threads-in-php-einfach-erstellen-mit-pthreads class AsyncOperation extends Thread { public function __construct($threadId) { $this->threadId = $threadId; } public function run() { printf("T %s: Sleeping 3sec\n", $this->threadId); sleep(3); printf("T %s: Hello World\n", $this->threadId); } } $start = microtime(true); for ($i = 1; $i <= 5; $i++) { $t[$i] = new AsyncOperation($i); $t[$i]->start(); } echo microtime(true) - $start . "\n"; echo "end\n";
Выходы
>php pthreads.php 0.041301012039185 end T 1: Sleeping 3sec T 2: Sleeping 3sec T 3: Sleeping 3sec T 4: Sleeping 3sec T 5: Sleeping 3sec T 1: Hello World T 2: Hello World T 3: Hello World T 4: Hello World T 5: Hello World