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

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

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

Ответ 1

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

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

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

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

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


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

Ответ 2

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

Примечание: чтобы избежать завершения php для завершения exec 'd script, выведите вывод в файл:

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

Альтернативно, вы можете преобразовать script с помощью PCNTL. Это использует один php script, который, когда 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
}

Ответ 4

Вы можете использовать более эффективную структуру данных, такую ​​как btree. Я использовал один раз в Java, но не в PHP. Вы можете попробовать этот script: 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

Ответ 5

Вопрос немного запутан.

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

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

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

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

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

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

"Я слышал", что pcntl не является хорошим решением. Любые переживания?

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

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

Вы можете найти их полезными:

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

С.

Ответ 6

Использование веб-интерфейса или CLI?

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

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

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

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

Ответ 7

Pthreads

Существует довольно новое (с 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