Multi Threading/Multi Tasking в PHP

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

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

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

Просьба предложить свои мысли и поделиться своим опытом, если вы уже делаете что-то вроде этого.

Я надеюсь, что нам еще нужно оптимизировать код.

Ответ 1

У PHP была многопоточная модель в течение очень долгого времени, начиная с первого выпуска PHP4, 22 мая 2000 года.

Потоки на интерфейсе

Создание пользовательских потоков во интерфейсе веб-приложения не имеет никакого смысла; его чрезвычайно сложно масштабировать. Нить на клиентскую модель, которую используют Apache Worker MPM и mod_php, на самом деле не является тем, что вы хотите использовать для обслуживания своих веб-сайтов, конечно, если вы ее используете, вы не хотите создавать дополнительные потоки в прямом ответе на любые веб-запросы.

Почему потоки в интерфейсе плохие?

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

Если клиент script создает 8 потоков в прямом ответе на веб-запрос, а 100 клиентов запрашивают script одновременно, вы запрашиваете, чтобы ваше оборудование выполняло потоки 800 одновременно.

CPU должен был бы выглядеть и работать очень по-разному, чтобы сделать это хорошей идеей

Что мы можем с этим сделать?

Предприимчивые решения могут иметь PHP-сайт, стоящий перед публикой, но фактические мозги системы написаны на языках, которые имеют хорошую поддержку для тех вещей, которые вам необходимы для создания таких предприимчивых решений, как Java, С#, С++ или любого другого языка -время.

Вы должны использовать pthreads таким же образом; путем проектирования систем, составные части которых отделены друг от друга, соединены только хорошо спроектированными, высокопроизводительными (RPC) API, так что сложность, присущая проектированию многопоточной архитектуры, полностью изолирована от ваших публичных веб-сайтов и простой, масштабируемую настройку, которую потребует такой веб-сайт.

U теперь может иметь коды ошибок

Начнем с начала с Hello World:

<?php
class My extends Thread {
    public function run() {
        printf("Hello World\n");
    }
}

/* create a new Thread */
$my = new My();

/* start the Thread */
$my->start();

/* do not allow PHP to manage the shutdown of your Threads */
/* if a variable goes out of scope in PHP it is destroyed */
/* joining explicitly ensures integrity of the data contained in an objects */
/* members while other contexts may be accessing them */
$my->join();
?>

Скучно, но, надеюсь, вы его прочитали;)

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

<?php
class My extends Threaded {
    public function run() {
        printf("Hello World from %s#%lu\n",
            __CLASS__, Thread::getCurrentThreadId());   
    }
}

/* create a Pool of four threads */
/* threads in a pool are created when required */
$pool = new Pool(4);

/* submit a few tasks to the pool */
$tasks = 100;
while ($tasks--) {
    $pool->submit(new My());
}

/* shutting down the pool is tantamount to joining all workers */
/* remember what I said about joining ? */
$pool->shutdown();
?>

Я дал вам краткие объяснения сложных вещей, вы должны попытаться прочитать все, что можете:

Много примеров можно найти здесь: https://github.com/krakjoe/pthreads/tree/master/examples

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

Ответ 2

Самый распространенный способ использования PHP - запустить его через многопроцессорный веб-сервер, такой как Apache. Это означает, что даже если сам PHP не является многоядерным, операционная система сделает все возможное, чтобы сбалансировать нагрузку, создаваемую процессами веб-сервера, между доступными ЦП.

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

Хотя стандартный дистрибутив PHP, похоже, не поддерживает потоки, существуют расширения, такие как php-pthreads, которые позволяют использовать native pthreads API.

Для разделения долговременной PHP-программы на несколько процессов вы можете использовать библиотеку pcntl или proc_* семейства функций. Что касается IPC.. снова, это зависит от ваших потребностей.

Ответ 3

Ну, как объяснение уже было предоставлено, поэтому прямое указание кода. Все, что вы спросили, может быть достигнуто с помощью Threads.

require_once( 'Thread.php' );

// test to see if threading is available
if( ! Thread::available() ) 
{
   die( 'Threads not supported' );
}

// function to be ran on separate threads
function paralel( $_limit, $_name ) 
{
    for ( $index = 0; $index < $_limit; $index++ ) 
    {
        echo 'Now running thread ' . $_name . PHP_EOL;
        sleep( 1 );
    }
}

// create 2 thread objects
$t1 = new Thread( 'paralel' );
$t2 = new Thread( 'paralel' );

// start them
$t1->start( 10, 't1' );
$t2->start( 10, 't2' );

// keep the program running until the threads finish
while( $t1->isAlive() && $t2->isAlive() ) 
{
}

Помните, что сам PHP не поддерживает Threads. Более подробную информацию можно найти здесь http://blog.motane.lu/2009/01/02/multithreading-in-php/

Вы также можете следовать этому ответу, что объясняет немного лучше, когда речь идет о PHP и Threads с примером кода.

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

Ответ 4

PHP на самом деле не спроектирован с многопоточным (он построен на модели запроса/ответа на короткий срок). Однако есть пара вариантов.

PCNTL extenstion: создавать и управлять дочерними процессами. Это не многопоточность, так как каждый дочерний процесс представляет собой новый экземпляр PHP. Поэтому он довольно ресурсоемкий. Недоступно в Windows.

Расширение PThreads: позволяет создавать нересты и управлять потоками в PHP script. Это (насколько я могу судить по документам), доступным в Windows, и потоки должны теоретически, по крайней мере, быть немного более легкими, чем процессы нереста, но есть множество предостережений для его использования. Например, ваш PHP должен быть скомпилирован для обеспечения безопасности потоков, что может отрицательно повлиять на производительность неподписанного кода и может предотвратить использование расширений, которые не поддерживают безопасность потоков.

ReactPHP: библиотека PHP-кода, которая обеспечивает такие функции, как цикл событий и неблокирующий IO. Он строго говорит о поддержке нитей (хотя я понимаю, что там они работают), но он обеспечивает много полезной функциональности, которая должна сделать нужную нить. https://github.com/reactphp/react/wiki/FAQ включает обсуждение состояния поддержки потоков.