PDA

Просмотр полной версии : Эмуляция многопоточности в PHP


S0meT1me
19.09.2010, 15:32
I ВСТУПЛЕНИЕ

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

Сразу отмечу, эмулировать многопоточность будем для работы с сетью, не для вычислительных процессов и прочего (ИМХО - здесь PHP не пригоден как интерпритируемый язык в связи со скоростью его выполнения).

Итак, рассмотрим способы реализации многопоточности в ПХП.

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

Такой подход подробно рассмотрен здесь (http://habrahabr.ru/blogs/php/40245/) . Стоит так же отметить, такой же подход использует класс функций multi_ библиотеки CURL.

2. Второй метод основан на эмуляцции многопоточности, используя многозадачность. Другими словами, наш скрипт просто запускает нужное число процессов, распределяя между ними входные данные нужным образом. Этот метод впервые был предложен на ачате здесь (https://antichat.live/threads/73234/) , так же интересная реализация этого метода предложена здесь (http://domaintimes.net/forum/showthread.php?t=7378) .

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

II РЕАЛИЗАЦИЯ

Функция для запуска эмуляции многопоточности


threads_create(

$threads,//число потоков

$copy_files,//файлы, нужные для работы аждого потока

$create_files,//исходные данные, которые ужно распределить между отоками

$run_files,//исполняемые файлы в рамка х каждого потока

$implode_files//результирующие данные, сф рмированные каждым из по оков, которые нужно собра ть в 1 файл

)

Вкратце алгоритм работы:

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


functionthreads_create($threads,$copy_files,$creat e_files,$run_files,$implode_files=array() ) {

$cfs= array();

foreach($create_filesas$fname=>$content) {

if( !is_array($content) ) {

$content=file2array($fname);

} else {

}

$cfs[$fname] =array_rand_slice($content,$threads);

}



$bat="@echo off\ncd thread0\n";

$tdir='threads-'.randstr(5);

mkdir($tdir);

chdir($tdir);



for($i=0;$i$fname)

copy('../'.$fname_from,$dir.'/'.$fname);



foreach(array_keys($cfs) as$fname )

file_put_contents($dir.'/'.$fname,str_replace("\n\n","\n",implode("\n",$cfs[$fname] [$i] ) ) );



$bat.="cd ..\\thread{$i}\n";

foreach($run_filesas$fname=>$params)

$bat.="start php$fname$params\n";

}



file_put_contents('run.bat',$bat);

exec('run.bat');

unlink('run.bat');



foreach($implode_filesas$if) {

$contents= array();

for($i=0;$i'do.php',//какие файлы копировать в папку к каждому потоку

),

array(

'accs.txt'=>'accs.txt',//какие файлы содержат данн ые, что надо равномерно р спределить между всеми п токами

),

array(

'do.php'=>'',//исполняемые файлы с набор ом параметров

),

array(

'accs.good.txt',//файл гуд акков, который н до собрать в результате аботы каждого из потоков

'accs.bad.txt'//файл бед акков

)

);

}

Спасибо за внимание.

Catbert
19.09.2010, 16:57
Но, существует немало задач, где она необходима. В рамках тематики данного форума это могут быть брутеры, спамеры, граберы, чекеры, инвайтеры, гулялки, заливщики.


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


Сразу отмечу, эмулировать многопоточность будем для работы с сетью, не для вычислительных процессов и прочего (ИМХО - здесь PHP не пригоден как интерпритируемый язык в связи со скоростью его выполнения).


Из-за скорости выполнения и нагрузки он и для работы с сетью с такими "потоками" не особо пригоден.

Далее рассмотрим кодэ.


if( !is_array( $content ) ) {
$content = file2array( $fname );
} else {
}


Else - пустое место? Сурово


$bat = "@echo off\ncd thread0\n";
.....
file_put_contents( 'run.bat', $bat );
exec('run.bat');
unlink('run.bat')


Причем нигде не указано, что решение исключительно под win.


function randel( $array ) {
return $array[ mt_rand( 0, count($array) - 1 ) ];
}


Ты не поверишь, но существует функция array_rand.


function file2array( $filename ) {
$array = array();
foreach( file( $filename ) as $row ) if( $row = trim( $row ) ) {
$array []= $row;
}
return $array;
}


Опять модная функция. Неведомая проверка тоже радует, ТС, специально для тебя у функции file есть специальный флаг FILE_IGNORE_NEW_LINES.

[QUOTE="None"]
function array_rand_slice( $array, $amount ) {
shuffle( $array );
$sliced = array();
$step = floor( count( $array ) / $amount );
for( $i = 0; $i

S0meT1me
19.09.2010, 18:38
И любой адекватный человек использует для этих целей другой язык программирования.


А ты загляни в топик продаж - таммного однопоточного софта на ПХП


Из-за скорости выполнения и нагрузки он и для работы с сетью с такими "потоками" не особо пригоден.


ты ещё скажи что для создания сайтов не пригоден

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


Ты не поверишь, но существует функция array_rand.


array_rand возвращает ключ, моя возвращает значение.


Бле, пересчет размера массива при каждой итерации...


PHP хеширует такие вещи


А тут в первой функции мы видим пересчет длины статической строки при каждом вызове. Не проще ли было воспользоваться функцией chr (например, chr(mt_rand(0x30, 127)))?


Проще с точки зрения скорости выполнения программы, но сложнее с точки зрения её читаемости


А во второй функции переменная $str вообще не инициализирована изначально.


Изначально она и так пуста/нул/ноль.


Ни в одной функции нет вообще никакой обработки ошибок. Даже если код где-то навернется, все равно продолжится его выполнение дальше. А навернуться тут очень много шансов.


Этот код работал уже годика полтора

З.Ы.: Catbert, чего так нервно? давно не трахался?

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

Catbert
19.09.2010, 19:24
А ты загляни в топик продаж - таммного однопоточного софта на ПХП


А в мире много безработных и нищих - это повод на них равняться?


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


Правда? Т.е. ты утверждаешь что при работе с сетью пхп покажет скорость аналогичную программе написанной на с++ скажем?


array_rand возвращает ключ, моя возвращает значение.


Т.е. лучше написать mt_rand( 0, count($array) - 1 , чем array_rand($array) ?

Ну да, конечно, лучше вызвать две функции чем одну.

$array[mt_rand( 0, count($array) - 1];

->

$array[array_rand($array)];


PHP хеширует такие вещи


В ассоциативный массив заносит штоле?


Этот код работал уже годика полтора


И Лада Калина может ездить полтора годика без поломки, однако она ни разу не пример качественного автомобилестроения.

GRRRL Power
19.09.2010, 19:27
А ты загляни в топик продаж - таммного однопоточного софта на ПХП


Все на пхп и пишут из-за того, что язык прост как зубочистка. А вы своей статьей провоцируете таких горе-кодеров не развиваться, изучая новые языки, а выжимать бесполезные вещи из всё того же php.


PHP хеширует такие вещи


Хеширует? Может быть, кеширует?

А вообще, я даже проверил это ради интереса. Ничего он там не кеширует.






Результаты:


Test 1: 0.170279979706
Test 2: 0.112259864807



Проще с точки зрения скорости выполнения программы, но сложнее с точки зрения её читаемости


А тут по-моему скорость важнее. А читаемость и так и так нормальна.


Изначально она и так пуста/нул/ноль.


Все же, она не пуста, она неопределена.


Этот код работал уже годика полтора


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

S0meT1me
20.09.2010, 00:58
Ох вы и злые... я ж не софт для запуска шатла писал, всё к словам да мелочам придираетесь. Уйду я от вас

Шутка, не дождётесь


Правда? Т.е. ты утверждаешь что при работе с сетью пхп покажет скорость аналогичную программе написанной на с++ скажем?


Скорость будет сравнима, т.е. отличаться будет не в десятки и сотни раз, а возможно даже и не в разы.

Catbert, чего ты злой такой? и всё к мелочам приколупываешься?


Все на пхп и пишут из-за того, что язык прост как зубочистка


Согласен, хотя и тут накодили такие вещи как CakePHP - довольно мощный фреймвёк.


Хеширует? Может быть, кеширует?


Ну вот, мы друг-друга поняли


Все же, она не пуста, она неопределена.


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