Въведение
PHP има пълен Multi-Threading подкрепа, от която можете да се възползвате напълно по толкова много начини. Успях да демонстрирам тази способност за многонишковост в различни примери:
- Как може да се използва многопоточно в PHP приложения
- pcntl изпълнява същия код няколко пъти, изисква се помощ
- Подобряване на ефективността на HTML scraper с pcntl_fork()
бързо търсене ще даде допълнителни ресурси.
Категории
1:MySQL заявки
MySQL е напълно многонишков и ще използва множество процесори, при условие че операционната система ги поддържа. Освен това ще увеличи максимално системните ресурси, ако е правилно конфигуриран за производителност.
Типична настройка в my.ini
които влияят върху производителността на нишката е:
thread_cache_size = 8
thread_cache_size може да се увеличи за подобряване на производителността, ако имате много нови връзки. Обикновено това не осигурява значително подобрение на производителността, ако имате добра реализация на нишката. Въпреки това, ако вашият сървър вижда стотици връзки в секунда, обикновено трябва да зададете thread_cache_size достатъчно високо, така че повечето нови връзки да използват кеширани нишки
Ако използвате Solaris след това можете да използвате
thread_concurrency = 8
thread_concurrency позволява на приложенията да дават на системата нишки намек за желания брой нишки, които трябва да се изпълняват едновременно.
Тази променлива е остаряла от 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:
@rdlowrey Цитат 2:
Защо не експериментирате с event-driven
, non-blocking I/O
подход към вашия проблем. PHP има libevent
за да допълните приложението си.
Знам, че този въпрос е изцяло Multi-Threading
но ако имате време, можете да погледнете този ядрен реактор, написан на PHP
от @igorw
Най-накрая
Разглеждане
Мисля, че трябва да помислите за използването на Cache
и Job Queue
за някои от вашите задачи. Можете лесно да получите съобщение, което казва
Document uploaded for processing ..... 5% - Done
След това правете всички задачи, които губите време във фонов режим. Моля, вижте Намаляване на голяма задача за обработка за подобен казус.
Профилиране
Инструмент за профилиране? Няма инструмент за един профил за уеб приложение от Xdebug до Yslow всички са много полезни. напр. Xdebug не е полезен, когато става въпрос за нишки, защото не се поддържа
Нямам фаворит