Ярлыки

.htaccess (4) тестирование (8) шаблоны проектирования (3) css (5) Debian (6) docker (2) Doctrine2 (6) Git (6) html (4) java (6) javascript (13) jquery (11) LFS (3) linux (23) mac os (4) mod_rewrite (2) MSSQL (4) MySQL (18) ORM Doctrine (17) patterns (3) PDO (3) perl (7) PHP (64) PHPUnit (8) Python (15) SEO (2) Silex (1) SimpleXML (1) SQL (14) ssh (4) Ubuntu (24) Yii1 (1) Zend Framework (19) ZendFramework2 (8)

воскресенье, 8 апреля 2012 г.

PHP. Многозадачность aka многопоточность.

Полноценных потоков(Threads), как в java, perl или python, в php нет. Но во многих случаях они и не нужны. Класс Pool создает новые процессы ос, запуская php скрипты и передавая им параметры командной строки. Взаимодействие между процессами можно реализовать различными способами, например, разделяемая память и семафоры, базы данных (sqlite в оперативной памяти), apc, memcache, файлы. Придется, разумеется, реализовать блокировки при записи из различных процессов, так как, например, apc и memcache их не имеют. Запускаем и смотрим:
Task ID: 1
Task ID: 0
Task ID: 2
Task ID: 3
Task ID: 4
Task ID: 5
Task ID: 6
Task ID: 7
Task ID: 8
Task ID: 9
Total time: 10 s
Видно, что скрипт выполнялся всего 10 секунд.

6 комментариев:

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

    while(false !== ($output = $mtasking->iterate()))
    if($output)
    echo $output;

    А именно вызов функции $mtasking->iterate()? Можно его удалить?
    У меня запускается много процессов, больше 200, И после того как все процессы выполнятся, получаю ошибку:
    Warning: stream_select() [function.stream-select]: unable to select [2]: No such file or directory (max_fd=1580) in Multitasking.php on line 34

    Если в общей сумме запускается не больше 100 процессов, то тогда ошибки нет.

    ОтветитьУдалить
    Ответы
    1. а вообще лучше изучите вот это
      https://en.wikipedia.org/wiki/Java_concurrency

      Удалить
  2. обязательно, именно он запускает процесс порождения процессов,
    а сколько задач вы создаете в цикле, второй операнд отвечает за их кол-во
    while($n < 10) ...
    ?

    ОтветитьУдалить
    Ответы
    1. Разве? Как я понял функция iterate(), отслеживает уже запущенные процессы на предмет появления символов, доступных для чтения, выводит их, и если процессы закончили свою задачу то закрывает их.
      А запускает новые процессы функция addTask(), так как именно в ней происходит вызов функции proc_open(). Или я не прав?

      Ошибка появляется если while($n < 64) и более, то есть при while($n < 63) ошибки нет. Много гуглил, но так ничего толкового не нашел. Сложилось впечатление что функция stream_select() попросту не способна отслеживать потоки, перечисленные в массиве "read", если их больше 63.

      Удалить
    2. Вы совершенно правы. Возможно проблема в реализации stream_select или это может зависеть от системы. В любом случае я бы посмотрел в сторону полноценной реализации многопоточности например в Java. Это не более чем костыль. Нет ни Concurrent Colletions, CycleBarrier и тд. Проблема во взаимодействии между потоками ...

      Удалить
  3. Прочитал описание функции stream_select(), в принципе понимаю что она делает. Но не могу понять что она делает конкретно в этом коде, для чего она нужна?

    ОтветитьУдалить