ANTICHAT

ANTICHAT (https://forum.antichat.xyz/index.php)
-   Статьи (https://forum.antichat.xyz/forumdisplay.php?f=30)
-   -   Эмуляция многопоточности в PHP (https://forum.antichat.xyz/showthread.php?t=230597)

S0meT1me 19.09.2010 15:32

I ВСТУПЛЕНИЕ

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

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

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

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

Такой подход подробно рассмотрен здесь . Стоит так же отметить, такой же подход использует класс функций multi_ библиотеки CURL.

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

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

II РЕАЛИЗАЦИЯ

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

PHP код:

[COLOR="#000000"][COLOR="#0000BB"]threads_create[/COLOR][COLOR="#007700"](

[/COLOR][COLOR="#0000BB"]$threads[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#FF8000"]//число потоков

[/COLOR][COLOR="#0000BB"]$copy_files[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#FF8000"]//файлы, нужные для работы каждого потока

[/COLOR][COLOR="#0000BB"]$create_files[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#FF8000"]//исходные данные, которые нужно распределить между потоками

[/COLOR][COLOR="#0000BB"]$run_files[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#FF8000"]//исполняемые файлы в рамках каждого потока

[/COLOR][COLOR="#0000BB"]$implode_files[/COLOR][COLOR="#FF8000"]//результирующие данные, сформированные каждым из потоков, которые нужно собрать в 1 файл

[/COLOR][COLOR="#007700"])[/COLOR][/COLOR

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

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

PHP код:

[COLOR="#000000"][COLOR="#0000BB"][/COLOR][COLOR="#007700"]function[/COLOR][COLOR="#0000BB"]threads_create[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$threads[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$copy_files[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$create_files[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$run_files[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$implode_files[/COLOR][COLOR="#007700"]=array() ) {

[/
COLOR][COLOR="#0000BB"]$cfs[/COLOR][COLOR="#007700"]= array();

foreach([/COLOR][COLOR="#0000BB"]$create_files[/COLOR][COLOR="#007700"]as[/COLOR][COLOR="#0000BB"]$fname[/COLOR][COLOR="#007700"]=>[/COLOR][COLOR="#0000BB"]$content[/COLOR][COLOR="#007700"]) {

if( ![/COLOR][COLOR="#0000BB"]is_array[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$content[/COLOR][COLOR="#007700"]) ) {

[/
COLOR][COLOR="#0000BB"]$content[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]file2array[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$fname[/COLOR][COLOR="#007700"]);

} else {

}

[/
COLOR][COLOR="#0000BB"]$cfs[/COLOR][COLOR="#007700"][[/COLOR][COLOR="#0000BB"]$fname[/COLOR][COLOR="#007700"]] =[/COLOR][COLOR="#0000BB"]array_rand_slice[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$content[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$threads[/COLOR][COLOR="#007700"]);

}



[/COLOR][COLOR="#0000BB"]$bat[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#DD0000"]"@echo off\ncd thread0\n"[/COLOR][COLOR="#007700"];

[/
COLOR][COLOR="#0000BB"]$tdir[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#DD0000"]'threads-'[/COLOR][COLOR="#007700"].[/COLOR][COLOR="#0000BB"]randstr[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]5[/COLOR][COLOR="#007700"]);

[/
COLOR][COLOR="#0000BB"]mkdir[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$tdir[/COLOR][COLOR="#007700"]);

[/
COLOR][COLOR="#0000BB"]chdir[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$tdir[/COLOR][COLOR="#007700"]);



for
([/COLOR][COLOR="#0000BB"]$i[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]0[/COLOR][COLOR="#007700"];[/COLOR][COLOR="#0000BB"]$i[/COLOR][COLOR="#007700"][/COLOR][COLOR="#0000BB"]$fname[/COLOR][COLOR="#007700"])

[/
COLOR][COLOR="#0000BB"]copy[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#DD0000"]'../'[/COLOR][COLOR="#007700"].[/COLOR][COLOR="#0000BB"]$fname_from[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$dir[/COLOR][COLOR="#007700"].[/COLOR][COLOR="#DD0000"]'/'[/COLOR][COLOR="#007700"].[/COLOR][COLOR="#0000BB"]$fname[/COLOR][COLOR="#007700"]);



foreach
([/COLOR][COLOR="#0000BB"]array_keys[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$cfs[/COLOR][COLOR="#007700"]) as[/COLOR][COLOR="#0000BB"]$fname[/COLOR][COLOR="#007700"])

[/COLOR][COLOR="#0000BB"]file_put_contents[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#0000BB"]$dir[/COLOR][COLOR="#007700"].[/COLOR][COLOR="#DD0000"]'/'[/COLOR][COLOR="#007700"].[/COLOR][COLOR="#0000BB"]$fname[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]str_replace[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#DD0000"]"\n\n"[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#DD0000"]"\n"[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]implode[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#DD0000"]"\n"[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$cfs[/COLOR][COLOR="#007700"][[/COLOR][COLOR="#0000BB"]$fname[/COLOR][COLOR="#007700"]] [[/COLOR][COLOR="#0000BB"]$i[/COLOR][COLOR="#007700"]] ) ) );



[/COLOR][COLOR="#0000BB"]$bat[/COLOR][COLOR="#007700"].=[/COLOR][COLOR="#DD0000"]"cd ..\\thread[/COLOR][COLOR="#007700"]{[/COLOR][COLOR="#0000BB"]$i[/COLOR][COLOR="#007700"]}[/COLOR][COLOR="#DD0000"]\n"[/COLOR][COLOR="#007700"];

foreach([/COLOR][COLOR="#0000BB"]$run_files[/COLOR][COLOR="#007700"]as[/COLOR][COLOR="#0000BB"]$fname[/COLOR][COLOR="#007700"]=>[/COLOR][COLOR="#0000BB"]$params[/COLOR][COLOR="#007700"])

[/COLOR][COLOR="#0000BB"]$bat[/COLOR][COLOR="#007700"].=[/COLOR][COLOR="#DD0000"]"start php[/COLOR][COLOR="#0000BB"]$fname[/COLOR][COLOR="#DD0000"][/COLOR][COLOR="#0000BB"]$params[/COLOR][COLOR="#DD0000"]\n"[/COLOR][COLOR="#007700"];

}



[/COLOR][COLOR="#0000BB"]file_put_contents[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#DD0000"]'run.bat'[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#0000BB"]$bat[/COLOR][COLOR="#007700"]);

[/
COLOR][COLOR="#0000BB"]exec[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#DD0000"]'run.bat'[/COLOR][COLOR="#007700"]);

[/
COLOR][COLOR="#0000BB"]unlink[/COLOR][COLOR="#007700"]([/COLOR][COLOR="#DD0000"]'run.bat'[/COLOR][COLOR="#007700"]);



foreach
([/COLOR][COLOR="#0000BB"]$implode_files[/COLOR][COLOR="#007700"]as[/COLOR][COLOR="#0000BB"]$if[/COLOR][COLOR="#007700"]) {

[/
COLOR][COLOR="#0000BB"]$contents[/COLOR][COLOR="#007700"]= array();

for([/COLOR][COLOR="#0000BB"]$i[/COLOR][COLOR="#007700"]=[/COLOR][COLOR="#0000BB"]0[/COLOR][COLOR="#007700"];[/COLOR][COLOR="#0000BB"]$i[/COLOR][COLOR="#007700"][/COLOR][COLOR="#DD0000"]'do.php'[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#FF8000"]//какие файлы копировать в папку к каждому потоку

[/COLOR][COLOR="#007700"]),

array(

[/
COLOR][COLOR="#DD0000"]'accs.txt'[/COLOR][COLOR="#007700"]=>[/COLOR][COLOR="#DD0000"]'accs.txt'[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#FF8000"]//какие файлы содержат данные, что надо равномерно распределить между всеми потоками

[/COLOR][COLOR="#007700"]),

array(

[/
COLOR][COLOR="#DD0000"]'do.php'[/COLOR][COLOR="#007700"]=>[/COLOR][COLOR="#DD0000"]''[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#FF8000"]//исполняемые файлы с набором параметров

[/COLOR][COLOR="#007700"]),

array(

[/
COLOR][COLOR="#DD0000"]'accs.good.txt'[/COLOR][COLOR="#007700"],[/COLOR][COLOR="#FF8000"]//файл гуд акков, который надо собрать в результате работы каждого из потоков

[/COLOR][COLOR="#DD0000"]'accs.bad.txt'[/COLOR][COLOR="#FF8000"]//файл бед акков

[/COLOR][COLOR="#007700"])

);

}[/
COLOR][/COLOR

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

Catbert 19.09.2010 16:57

Цитата:

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

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

Цитата:

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

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

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

Цитата:

Сообщение от None
if( !is_array( $content ) ) {
$content = file2array( $fname );
} else {
}

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

Цитата:

Сообщение от None
$bat = "@echo off\ncd thread0\n";
.....
file_put_contents( 'run.bat', $bat );
exec('run.bat');
unlink('run.bat')

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

Цитата:

Сообщение от None
function randel( $array ) {
return $array[ mt_rand( 0, count($array) - 1 ) ];
}

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

Цитата:

Сообщение от None
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

Цитата:

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

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

Цитата:

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

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

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

Цитата:

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

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

Цитата:

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

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

Цитата:

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

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

Цитата:

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

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

Цитата:

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

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

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

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

Catbert 19.09.2010 19:24

Цитата:

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

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

Цитата:

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

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

Цитата:

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

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

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

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

->

$array[array_rand($array)];

Цитата:

Сообщение от None
PHP хеширует такие вещи

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

Цитата:

Сообщение от None
Этот код работал уже годика полтора

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

GRRRL Power 19.09.2010 19:27

Цитата:

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

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

Цитата:

Сообщение от S0meT1me
PHP хеширует такие вещи

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

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

PHP код:

[COLOR="#000000"][COLOR="#0000BB"][/COLOR][COLOR="#007700"]

[/
COLOR][/COLOR

Результаты:

Код:

Test 1: 0.170279979706
Test 2: 0.112259864807

Цитата:

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

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

Цитата:

Сообщение от S0meT1me
Изначально она и так пуста/нул/ноль.

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

Цитата:

Сообщение от S0meT1me
Этот код работал уже годика полтора

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

S0meT1me 20.09.2010 00:58

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

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

Цитата:

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

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

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

Цитата:

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

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

Цитата:

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

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

Цитата:

Сообщение от None
Все же, она не пуста, она неопределена.

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


Время: 02:27