Введение
PHP имеет полную поддержку многопоточности, которой вы можете в полной мере воспользоваться многими способами. Удалось продемонстрировать эту способность многопоточности на различных примерах:
быстрый поиск предоставит дополнительные ресурсы.
Категории
1: MySQL-запросы
MySQL полностью мульти- многопоточным и будет использовать несколько процессоров при условии, что их поддерживает операционная система. При правильной настройке производительности он также максимизирует системные ресурсы.
Типичный параметр my.ini, влияющий на производительность потока:
thread_cache_size = 8
thread_cache_size можно увеличить для повышения производительности если у вас много новых связей. Обычно это не дает заметного улучшения производительности, если у вас есть хорошая реализация потока. Однако, если ваш сервер видит сотни подключений в секунду, вы должны обычно устанавливать thread_cache_size достаточно высоким, чтобы большинство новых подключений использовали кешированные потоки.
Если вы используете Solaris, тогда вы можно использовать
thread_concurrency = 8
thread_concurrency позволяет приложениям предоставлять потоки system подсказка о желаемом количестве потоков, которые должны выполняться одновременно.
Эта переменная устарела в MySQL 5.6.1 и удалена в MySQL 5.7. Вы должны удалять это из файлов конфигурации MySQL всякий раз, когда вы видите это, если они не предназначены для Solaris 8 или более ранней версии.
InnoDB::
У вас нет таких ограничений, если вы используете Innodb имеет механизм хранения, потому что он полностью поддерживает параллелизм потоков
innodb_thread_concurrency // Recommended 2 * CPUs + number of disks
Вы также можете посмотреть innodb_read_io_threads и innodb_write_io_threads, где по умолчанию 4, и его можно увеличить до 64 в зависимости от оборудования.
Другое:
Другие конфигурации, на которые также стоит обратить внимание, включают key_buffer_size, table_open_cache, sort_buffer_size и т. Д., Которые все приводят к лучшей производительности.
PHP:
В чистом PHP вы можете создать MySQL Worker, где каждый запрос выполняется в отдельных потоках PHP.
$sql = new SQLWorker($host, $user, $pass, $db);
$sql->start();
$sql->stack($q1 = new SQLQuery("One long Query"));
$sql->stack($q2 = new SQLQuery("Another long Query"));
$q1->wait();
$q2->wait();
// Do Something Useful
Вот полный рабочий пример SQLWorker
2: синтаксический анализ содержимого HTML
Я подозреваю, что на эту задачу уходит много вычислительного времени.
Если вы уже знаете проблему, ее проще решить с помощью циклов событий, очереди заданий или с помощью потоков.
Работа с одним документом по отдельности может быть очень, очень медленным и болезненным процессом. @ka однажды нашел выход, используя ajax для вызова множественных запросов. Некоторые творческие умы просто разветвляли процесс, используя pcntl_fork, но если вы используете windows, вы не можете воспользоваться pcntl
Поскольку pThreads поддерживает как Windows, так и системы Unix, у вас нет такого ограничения. Это так просто, как .. Если нужно разобрать 100 документов? Создайте 100 потоков ... Просто
Сканирование HTML
// Scan my System
$dir = new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS);
$dir = new RecursiveIteratorIterator($dir);
// Allowed Extension
$ext = array(
"html",
"htm"
);
// Threads Array
$ts = array();
// Simple Storage
$s = new Sink();
// Start Timer
$time = microtime(true);
$count = 0;
// Parse All HTML
foreach($dir as $html) {
if ($html->isFile() && in_array($html->getExtension(), $ext)) {
$count ++;
$ts[] = new LinkParser("$html", $s);
}
}
// Wait for all Threads to finish
foreach($ts as $t) {
$t->join();
}
// Put The Output
printf("Total Files:\t\t%s \n", number_format($count, 0));
printf("Total Links:\t\t%s \n", number_format($t = count($s), 0));
printf("Finished:\t\t%0.4f sec \n", $tm = microtime(true) - $time);
printf("AvgSpeed:\t\t%0.4f sec per file\n", $tm / $t);
printf("File P/S:\t\t%d file per sec\n", $count / $tm);
printf("Link P/S:\t\t%d links per sec\n", $t / $tm);
Вывод
Total Files: 8,714
Total Links: 105,109
Finished: 108.3460 sec
AvgSpeed: 0.0010 sec per file
File P/S: 80 file per sec
Link P/S: 907 links per sec
Используемый класс
Sink
class Sink extends Stackable {
public function run() {
}
}
LinkParser
class LinkParser extends Thread {
public function __construct($file, $sink) {
$this->file = $file;
$this->sink = $sink;
$this->start();
}
public function run() {
$dom = new DOMDocument();
@$dom->loadHTML(file_get_contents($this->file));
foreach($dom->getElementsByTagName('a') as $links) {
$this->sink[] = $links->getAttribute('href');
}
}
}
Эксперимент
Пробуем разобрать 8,714 файлы со ссылками 105,109 без потоков и посмотреть, сколько времени это займет.
Лучшая архитектура
Создание слишком большого количества потоков, что неразумно в продакшене. Лучшим подходом было бы использовать пул. Создайте пул определенных работников, затем стек с Task
Повышение производительности
Хорошо, приведенный выше пример еще можно улучшить. Вместо того, чтобы ждать, пока система просканирует все файлы в одном потоке, вы можете использовать несколько потоков для сканирования моей системы на наличие файлов, а затем складывать данные в Workers для обработки.
3. Обновление поискового индекса
На этот вопрос в значительной степени ответил первый ответ, но есть много способов улучшить производительность. Вы когда-нибудь задумывались о подходе, основанном на событиях?
Знакомство с событием
@rdlowrey Цитата 1:
Подумайте об этом так. Представьте, что вам нужно обслужить 10 000 одновременно подключенных клиентов в вашем веб-приложении. Традиционные серверы thread-per-request или process-per-request не подходят, потому что независимо от того, насколько легковесны ваши потоки, вы все равно не сможете удержать 10 000 из них открытыми. вовремя.
@rdlowrey Цитата 2:
С другой стороны, если вы сохраняете все сокеты в одном процессе и слушаете, чтобы эти сокеты стали доступными для чтения или записи, вы можете поместить весь свой сервер в один цикл событий и работать с каждым сокетом только тогда, когда есть что-то для чтения / записи.
Почему бы вам не поэкспериментировать с event-driven, non-blocking I/O подходом к вашей проблеме. В PHP есть libevent, который ускоряет работу вашего приложения.
Я знаю, что это весь Multi-Threading вопрос, но если у вас есть время, вы можете посмотреть этот Nuclear Reactor, написанный на PHP, @igorw
Ну наконец то
Рассмотрение
Я думаю, вам следует подумать об использовании Cache и Job Queue для некоторых ваших задач. Вы можете легко написать сообщение
Document uploaded for processing ..... 5% - Done
Затем выполняйте все задачи, которые тратят впустую, в фоновом режиме. См. Уменьшение размера большого задания по обработке для аналогичного тематическое исследование.
Профилирование
Инструмент профилирования? Не существует единого инструмента профиля для веб-приложения от Xdebug до Yslow очень полезны. Например. Xdebug бесполезен, когда дело доходит до потоков, потому что он не поддерживается
У меня нет любимого
person
Baba
schedule
29.05.2013