Internet Windows Android
Kengaytirish

Pthreads Translation yordamida PHPda ko'p tarmoqli dasturlash. Windows Anemic muhokama mavzusi php uchun PHP versiyasini tanlash

Ko'rinishidan, PHP ishlab chiquvchilari parallellikdan kamdan-kam foydalanadilar. Men sinxron kodning soddaligi haqida gapirmayman, albatta, oddiyroq va tushunarliroq, lekin ba'zida parallelizmdan ozgina foydalanish unumdorlikni sezilarli darajada oshirishi mumkin;

Ushbu maqolada biz pthreads kengaytmasi yordamida PHP da multithreadingga qanday erishish mumkinligini ko'rib chiqamiz. Buning uchun PHP 7.x ning ZTS (Zend Thread Safety) versiyasi va o‘rnatilgan pthreads v3 kengaytmasi talab qilinadi. (Yozish vaqtida PHP 7.1 da foydalanuvchilar pthreads omboridagi asosiy filialdan o'rnatishlari kerak - uchinchi tomon kengaytmasiga qarang.)

Kichik tushuntirish: pthreads v2 PHP 5.x uchun mo‘ljallangan va endi qo‘llab-quvvatlanmaydi, pthreads v3 PHP 7.x uchun mo‘ljallangan va faol ishlab chiqilmoqda.

Bunday chekinishdan keyin to'g'ridan-to'g'ri mavzuga o'taylik!

Bir martalik vazifalarni qayta ishlash

Ba'zan siz bir martalik vazifalarni ko'p bosqichli usulda qayta ishlashni xohlaysiz (masalan, ba'zi bir kiritish/chiqarish bilan bog'liq vazifalarni bajarish). Bunday hollarda siz Thread sinfidan yangi ip yaratishingiz va alohida ish zarrachasida ba'zi ishlovlarni bajarishingiz mumkin.

Masalan:

$task = yangi sinf mavzuni kengaytiradi ( xususiy $response; umumiy funktsiyani ishga tushirish() ( $content = file_get_contents("http://google.com"); preg_match("~ (.+)~", $content, $matches); $this->response = $matches; ) ); $task->start() && $task->join(); var_dump($task->response); // string (6) "Google"

Bu erda ishga tushirish usuli bizning qayta ishlashimiz bo'lib, u yangi ip ichida bajariladi. Thread::start chaqirilganda, yangi ip paydo bo'ladi va ishga tushirish usuli chaqiriladi. Keyin biz Thread::join ga qo'ng'iroq qilish orqali asosiy ipni yana asosiy ipga birlashtiramiz, bu esa bola ipi bajarilishini tugatmaguncha bloklanadi. Bu biz natijani chop etishga urinishdan oldin vazifa bajarilishini ta'minlaydi (u $task->response da saqlanadi).

Sinfni oqim mantig'i bilan bog'liq qo'shimcha mas'uliyat (jumladan, ishga tushirish usulini belgilash mas'uliyati) bilan ifloslantirish istalmagan bo'lishi mumkin. Bunday sinflarni Threaded sinfidan meros qilib olish orqali farqlashimiz mumkin. Keyin ular boshqa ip ichida ishga tushirilishi mumkin:

Sinf vazifasi Threaded-ni kengaytiradi ( public $response; public function someWork() ( $content = file_get_contents("http://google.com"); preg_match("~ (.+) ~", $content, $matches); $ this->javob = $ mos keladi ) ) $task = new Task; $thread = new class($task) Thread kengaytiradi ( private $task; public function __construct(Threaded $task) ( $this->task = $task; ) public function run() ( $this->task->someWork() ); $thread->start() && $thread->join(); var_dump($task->javob);

Alohida ish zarrachasida ishlashi kerak bo'lgan har qanday sinf kerak Threaded sinfidan meros. Buning sababi shundaki, u turli xil oqimlarda ishlov berishni amalga oshirish uchun zarur imkoniyatlarni, shuningdek, yashirin xavfsizlik va foydali interfeyslarni (resurslarni sinxronlashtirish kabi) ta'minlaydi.

Keling, pthreads kengaytmasi tomonidan taqdim etilgan sinf ierarxiyasini ko'rib chiqaylik:

Threaded (Traversable, Collectable) Thread Worker uchuvchi hovuzni amalga oshiradi

Biz allaqachon Thread va Threaded sinflarining asoslarini qamrab oldik va o'rgandik, endi qolgan uchtasini ko'rib chiqamiz (Worker, Volatile va Pool).

Mavzularni qayta ishlatish

Parallellashtirilishi kerak bo'lgan har bir vazifa uchun yangi mavzuni boshlash juda qimmat. Buning sababi, PHP ichida ko'p ish zarralariga erishish uchun pthreadlarda umumiy-hech narsa arxitekturasini amalga oshirish kerak. Bu shuni anglatadiki, PHP tarjimonining joriy nusxasining butun ijro konteksti (shu jumladan, har bir sinf, interfeys, xususiyat va funksiya) yaratilgan har bir ip uchun nusxalanishi kerak. Bu sezilarli ishlash ta'siriga ega bo'lganligi sababli, oqim har doim imkon qadar qayta ishlatilishi kerak. Mavzularni ikki xil usulda qayta ishlatish mumkin: Workers yoki Pools yordamida.

Ishchi sinfi boshqa ish zarrachasi ichida bir qator vazifalarni sinxron ravishda bajarish uchun ishlatiladi. Bu yangi Ishchi misolini yaratish (yangi ish zarrachasini yaratuvchi) va keyin vazifalarni alohida ish stekasiga surish (Worker::stack yordamida) orqali amalga oshiriladi.

Mana kichik bir misol:

Sinf vazifasini kengaytiradi Threaded ( xususiy $value; public function __construct(int $i) ( $this->value = $i; ) public function run() ( usleep(250000); echo "Vazifa: ($this->qiymat) \n"; ) ) $ishchi = yangi ishchi(); $worker->start(); for ($i = 0; $i stack(new Task($i)); ) while ($worker->collect()); $worker->shutdown();

Yuqoridagi misolda yangi $worker obyekti uchun 15 ta vazifa Worker::stack usuli orqali stekga suriladi va keyin ular surilgan tartibda qayta ishlanadi. Ishchi::to'plash usuli, yuqorida ko'rsatilganidek, vazifalarni bajarish tugashi bilanoq ularni tozalash uchun ishlatiladi. U bilan, bir muncha vaqt oralig'ida, biz stekdagi barcha vazifalar bajarilmaguncha va tozalanmaguncha asosiy ipni bloklaymiz - biz Worker::shutdown ni chaqirishdan oldin. Ishchini erta tugatish (ya'ni, hali bajarilishi kerak bo'lgan vazifalar mavjud bo'lganda) barcha vazifalar bajarilishini tugatmaguncha asosiy mavzuni bloklaydi, shunchaki vazifalar axlat yig'ilmaydi (bu xotira oqishini anglatadi).

Ishchi sinfi o'zining vazifalar stekiga tegishli bir qancha boshqa usullarni taqdim etadi, jumladan, oxirgi yig'ilgan vazifani o'chirish uchun Worker::unstack va bajarilish stekidagi vazifalar sonini olish uchun Worker::getStacked. Ishchilar to'plami faqat bajarilishi kerak bo'lgan vazifalarni o'z ichiga oladi. Stekdagi vazifa bajarilgandan so'ng, u olib tashlanadi va axlat yig'ish uchun alohida (ichki) stekga joylashtiriladi (Worker::collect usuli yordamida).

Bir nechta vazifalarda ipni qayta ishlatishning yana bir usuli - bu iplar hovuzidan foydalanish (Pool klassi orqali). Mavzular hovuzi vazifalarni bajarish uchun Ishchilar guruhidan foydalanadi bir vaqtning o'zida, bunda hovuz yaratilganda parallellik omili (u bilan ishlaydigan hovuz iplari soni) o'rnatiladi.

Keling, yuqoridagi misolni ishchilar pulidan foydalanishga moslashtiramiz:

Sinf vazifasini kengaytiradi Threaded ( xususiy $value; public function __construct(int $i) ( $this->value = $i; ) public function run() ( usleep(250000); echo "Vazifa: ($this->qiymat) \n"; ) ) $hovuz = yangi Hovuz(4); for ($i = 0; $i submit(new Task($i)); ) while ($pool->collect()); $pool->shutdown();

Ishchidan farqli o'laroq, hovuzdan foydalanishda bir nechta sezilarli farqlar mavjud. Birinchidan, hovuzni qo'lda ishga tushirishning hojati yo'q, ular mavjud bo'lishi bilanoq u vazifalarni bajarishni boshlaydi. Ikkinchidan, biz yuborish hovuzga vazifalar, emas ularni to'plamga qo'ying. Bundan tashqari, Pool klassi Threaded-dan meros bo'lmaydi va shuning uchun boshqa ish zarrachalariga o'tkazib bo'lmaydi (Ishchidan farqli o'laroq).

Ishchilar va hovuzlar har doim o'z vazifalarini bajarishlari bilanoq tozalashlari va keyin ularni o'zlari qo'lda tugatishlari yaxshi amaliyotdir. Thread klassi yordamida yaratilgan mavzular ham asosiy ipga biriktirilishi kerak.

pthreads va (im)mutability

Biz to'xtaladigan oxirgi sinf - bu uchuvchi, pthreads v3 ga yangi qo'shilgan. O'zgarmaslik pthreadlarda muhim tushunchaga aylandi, chunki usiz ishlash sezilarli darajada yomonlashadi. Shuning uchun, sukut bo'yicha, o'zlari Threaded ob'ektlari bo'lgan Threaded sinflarining xususiyatlari endi o'zgarmasdir va shuning uchun ularni dastlabki tayinlanganidan keyin qayta yozib bo'lmaydi. Bunday xususiyatlar uchun aniq o'zgaruvchanlik hozirda afzal ko'riladi va hali ham yangi Volatile klassi yordamida erishish mumkin.

Keling, yangi o'zgarmaslik cheklovlarini ko'rsatadigan misolni ko'rib chiqaylik:

Sinf vazifasi Threaded-ni kengaytiradi // Threaded sinf ( umumiy funktsiya __construct() ( $this->data = new Threaded(); // $this->ma'lumotlar qayta yozilmaydi, chunki u Threaded sinfining Threaded xususiyatidir ) ) $task = new class(new Task()) Thread kengaytiradi ( // a Threaded klass, chunki Thread Threaded umumiy funksiyasini kengaytiradi __construct($tm) ( $this->threadedMember = $tm; var_dump($this->threadedMember-> data // object(Threaded)#3 (0) () $this->threadedMember = new StdClass(); bu xususiyat Threaded sinfining Threaded a'zosi bo'lgani uchun ) );

Boshqa tomondan, uchuvchi sinflarning tishli xususiyatlari o'zgaruvchan:

Sinf topshirig'i uchuvchanlikni kengaytiradi ( umumiy funktsiya __construct() ( $this->data = new Threaded(); $this->data = new StdClass(); // amal qiladi, chunki biz o'zgaruvchan sinfdamiz ) ) $task = new class(new Task()) mavzuni kengaytiradi ( umumiy funktsiya __construct($vm) ( $this->volatileMember = $vm; var_dump($this->volatileMember->data); // object(stdClass)#4 (0) () // hali ham yaroqsiz, chunki Volatile Threaded-ni kengaytiradi, shuning uchun xususiyat hali ham Threaded sinfining Threaded a'zosi $this->volatileMember = new StdClass() );

Ko'rishimiz mumkinki, Volatile klassi Threaded xususiyatlarini o'zgartirish imkoniyatini (shuningdek, ularni unset()) ta'minlash uchun o'zining asosiy Threaded klassi tomonidan o'rnatilgan o'zgarmaslikni bekor qiladi.

O'zgaruvchanlik va O'zgaruvchanlik klassi - massivlar mavzusini yoritish uchun yana bir muhokama mavzusi mavjud. Pthreadlarda massivlar Threaded sinfining xususiyatiga tayinlanganda avtomatik ravishda Volatile ob'ektlarga o'tkaziladi. Buning sababi, bir nechta PHP kontekstlari massivlarini boshqarish xavfsiz emas.

Ba'zi narsalarni yaxshiroq tushunish uchun yana bir misolni ko'rib chiqaylik:

$massiv =; $task = new class($array) kengaytiradi Mavzu ( xususiy $data; umumiy funktsiya __construct(massiv $massiv) ( $this->data = $array; ) umumiy funktsiya run() ( $this->data = 4; $ this->data = 5 print_r($this->ma'lumotlar) ); $task->start() && $task->join(); /* Chiqish: oʻzgaruvchan obyekt ( => 1 => 2 => 3 => 4 => 5) */

Biz uchuvchan ob'ektlarni massivlar kabi ko'rib chiqish mumkinligini ko'ramiz, chunki ular (yuqorida ko'rsatilganidek) subset() operatori kabi massiv operatsiyalarini qo'llab-quvvatlaydi. Biroq, o'zgaruvchan sinflar array_pop va array_shift kabi asosiy massiv funksiyalarini qo'llab-quvvatlamaydi. Buning o'rniga, Threaded klassi bizga o'rnatilgan usullar kabi operatsiyalarni taqdim etadi.

Namoyish sifatida:

$ma'lumotlar = yangi sinf O'zgaruvchan (ommaviy $a = 1; umumiy $b = 2; ommaviy $c = 3; ); var_dump($ma'lumotlar); var_dump($data->pop()); var_dump($data->shift()); var_dump($ma'lumotlar); /* Chiqish: obyekt(sinf@anonim)#1 (3) ( ["a"]=> int(1) ["b"]=> int(2) ["c"]=> int(3) ) int(3) int(1) obyekti(sinf@anonim)#1 (1) (["b"]=> int(2) ) */

Boshqa qo'llab-quvvatlanadigan operatsiyalarga Threaded::chunk va Threaded::merge kiradi.

Sinxronizatsiya

Ushbu maqolaning oxirgi qismida biz pthreadlardagi sinxronizatsiyani ko'rib chiqamiz. Sinxronizatsiya - bu umumiy resurslarga kirishni boshqarish imkonini beruvchi usul.

Masalan, oddiy hisoblagichni amalga oshiramiz:

$counter = yangi sinf kengaytiriladi Thread ( public $i = 0; public function run() (for ($i = 0; $i i; ) ) ); $counter->start(); uchun ($i = 0; $i i; ) $counter->join(); var_dump($counter->i); // 10 dan 20 gacha raqamni chop etadi

Sinxronizatsiyadan foydalanmasdan, chiqish deterministik emas. Bir nechta iplar bir xil o'zgaruvchiga boshqariladigan ruxsatsiz yozadi, bu yangilanishlar yo'qolishini anglatadi.

Keling, vaqtni qo'shish orqali 20 ning to'g'ri chiqishini olishimiz uchun buni tuzatamiz:

$counter = new class extensions Thread ( public $i = 0; public function run() ( $this->synchronized(function () (for ($i = 0; $i i; ) ); ) ); $counter->start(); $counter->synchronized(funktsiya ($counter) (uchun ($i = 0; $i i; ) ), $counter); $counter->join(); var_dump($counter->i); // int (20)

Sinxronlashtirilgan kod bloklari Threaded::wait va Threaded::notify (yoki Threaded::notifyAll) usullari yordamida ham bir-biri bilan bog'lanishi mumkin.

Mana ikkita sinxronlashtirilgan while tsiklidagi muqobil o'sish:

$counter = yangi sinfni kengaytiradi Thread ( public $cond = 1; public function run() ( $this->synchronized(function () (for ($i = 0; $i notify(); if ($this->cond) === 1) ( $this->cond = 2; $this->wait(); ) ) )); $counter->start(); $counter->synchronized(funksiya ($counter) ( if ($counter->cond !== 2) ( $counter->wait(); // birinchi navbatda ikkinchisi boshlanishini kuting ) uchun ($i = 10; $i notify(); if ($counter->cond === 2) ( $counter->cond = 1; $counter->wait(); ) ) ), $counter); $counter->join(); /* Chiqish: int(0) int(10) int(1) int(11) int(2) int(12) int(3) int(13) int(4) int(14) int(5) int( 15) int(6) int(16) int(7) int(17) int(8) int(18) int(9) int(19) */

Threaded::wait ga qo'ng'iroq qilish atrofida qo'shimcha shartlar mavjudligini ko'rishingiz mumkin. Ushbu shartlar juda muhim, chunki ular bildirishnoma olganida va belgilangan shart rost bo'lganda sinxronlashtirilgan qayta qo'ng'iroqni davom ettirishga imkon beradi. Bu muhim, chunki bildirishnomalar Threaded::notify chaqirilgandan boshqa joylardan kelishi mumkin. Shunday qilib, agar Threaded::wait usuliga qo'ng'iroqlar shartlarga kiritilmagan bo'lsa, biz bajaramiz. noto'g'ri qo'ng'iroqlar, bu oldindan aytib bo'lmaydigan kod xatti-harakatlariga olib keladi.

Xulosa

Biz pthreads to'plamining beshta sinfini (Threaded, Thread, Worker, Volatile va Pool) va har bir sinfdan qanday foydalanishni ko'rib chiqdik. Shuningdek, biz pthreadlardagi o'zgarmaslikning yangi kontseptsiyasini ko'rib chiqdik va qo'llab-quvvatlanadigan sinxronizatsiya imkoniyatlari haqida qisqacha ma'lumot berdik. Ushbu asoslar mavjud bo'lsa, biz endi haqiqiy dunyo holatlarida pthreadlardan qanday foydalanish mumkinligini ko'rib chiqishni boshlashimiz mumkin! Bu bizning keyingi postimizning mavzusi bo'ladi.

Agar siz keyingi postning tarjimasi bilan qiziqsangiz, menga xabar bering: ijtimoiy tarmoqlarda sharh qoldiring. tarmoqlar, ovoz bering va postni hamkasblar va do'stlar bilan baham ko'ring.

Ba'zan bir vaqtning o'zida bir nechta harakatlarni bajarish kerak bo'ladi, masalan, bitta ma'lumotlar bazasi jadvalidagi o'zgarishlarni tekshirish va boshqasiga o'zgartirishlar kiritish. Bundan tashqari, agar operatsiyalardan biri (masalan, o'zgarishlarni tekshirish) ko'p vaqtni talab qilsa, ketma-ket bajarish resurslarni muvozanatlashni ta'minlamasligi aniq.

Ushbu turdagi muammolarni hal qilish uchun dasturlash ko'p ish zarralarini ishlatadi - har bir operatsiya ajratilgan resurslar miqdori bilan alohida trekka joylashtiriladi va uning ichida ishlaydi. Ushbu yondashuv bilan barcha vazifalar alohida va mustaqil ravishda bajariladi.

PHP ko'p ish zarralarini qo'llab-quvvatlamasa ham, uni taqlid qilishning bir necha usullari mavjud, ular quyida muhokama qilinadi.

1. Skriptning bir nechta nusxalarini ishga tushirish - har bir operatsiya uchun bitta nusxa

//woman.php if (!isset($_GET["thread"])) ( system("wget ​​http://localhost/woman.php?thread=make_me_happy"); system("wget ​​http: //localhost/ woman.php?thread=make_me_rich"); ) elseif ($_GET["thread"] == "me_me_happy") ( make_her_happy(); ) elseif ($_GET["thread"] == "me_rich" ) (boshqa_bir_topish( ); )

Ushbu skriptni parametrlarsiz bajarganimizda, u avtomatik ravishda kerakli funktsiyalarni bajarishni boshlaydigan operatsiya identifikatorlari ("thread=make_me_happy" va "thread=make_me_rich") bilan o'zining ikkita nusxasini ishga tushiradi.

Shunday qilib, biz kerakli natijaga erishamiz - ikkita operatsiya bir vaqtning o'zida amalga oshiriladi - lekin bu, albatta, ko'p ish zarralari emas, balki oddiygina vazifalarni bir vaqtning o'zida bajarish uchun tayoqchadir.

2. Jedi yo'li - PCNTL kengaytmasidan foydalanish

PCNTL - bu jarayonlar bilan to'liq ishlash imkonini beruvchi kengaytma. Boshqaruvdan tashqari, u xabarlarni yuborish, holatni tekshirish va ustuvorliklarni belgilashni qo'llab-quvvatlaydi. PCNTL yordamida oldingi skript shunday ko'rinadi:

$pid = pcntl_fork(); if ($pid == 0) ( make_her_happy(); ) elseif ($pid > 0) ( $pid2 = pcntl_fork(); if ($pid2 == 0) ( find_another_one(); ) )

Bu juda chalkash ko'rinadi, keling, uni qatorma-bosqich ko'rib chiqaylik.

Birinchi qatorda biz joriy jarayonni "vilka" qilamiz (vilka barcha o'zgaruvchilar qiymatlarini saqlab qolgan holda jarayonni nusxalash), uni parallel ravishda ishlaydigan ikkita jarayonga (joriy va bola) ajratamiz.

Biz hozirda bola yoki ona jarayonida ekanligimizni tushunish uchun pcntl_fork funktsiyasi bola uchun 0 va ona uchun jarayon identifikatorini qaytaradi. Shuning uchun, ikkinchi qatorda biz $pid ga qaraymiz, agar u nol bo'lsa, u holda biz bola jarayonidamiz - biz funktsiyani bajaramiz, aks holda biz onadamiz (4-qator), keyin biz boshqa jarayonni yaratamiz va xuddi shunday vazifani bajaring.

Skriptni bajarish jarayoni:

Shunday qilib, skript uning nusxalari bo'lgan va o'xshash qiymatlarga ega bir xil o'zgaruvchilarni o'z ichiga olgan yana 2 ta asosiy jarayonni yaratadi. Va pcntl_fork funktsiyasi tomonidan qaytarilgan identifikatordan foydalanib, biz hozirda qaysi ipda ekanligimizni bilib olamiz va kerakli harakatlarni bajaramiz.

Diqqat! Ushbu maqola umidsiz ravishda eskirgan yoki muallif tomonidan hech qanday ma'lumotga ega emas deb baholanadi.

Ochiq kodli kodning go'zalligi uning ochiqligida :)) Ya'ni. agar sizda aql/vaqt/istak bo'lsa, dastur qanday ishlashini aniq bilib olishingiz mumkin. Bunday kodning salbiy tomoni - kerakli kompilyatsiya qilingan paketlarni olish qiyinligi. Misol uchun, PHP Nix tizimlari uchun manba sifatida keyingi kompilyatsiya/montaj bilan yuklab olinishi mumkin. Windows uchun hamma narsa allaqachon yig'ilgan, ammo juda ko'p tayyor ikkilik paketlar mavjud! " bilan variantlar ip xavfsiz / ipsiz xavfsiz", VC6/VC9 va PHP ning turli versiyalari. Maqola vaziyatga oydinlik kiritish uchun yaratilgan. U turli manbalarga, qisman ingliz tilidan tarjimaga asoslangan. Buni keyingi safar yana o'ylab ko'rishga to'g'ri kelmasligi uchun - "nima foyda!?"

Kerakli PHP versiyasi u ishlatiladigan veb-server versiyasiga bog'liq. Masalan, Apache 1.3.x PHP 3.0.x versiyasi bilan ishlaydi, Apache 2.x PHP 4.0 va undan yuqori versiyalari bilan ishlaydi. Ammo bu unchalik muammo emas, yangi barqaror nashrlarga va hosterda nima borligiga e'tibor qarating.

Qanday postkriptlar VC6, VC9, VC11? Windows uchun PHP manbalari Visual Studio dasturida tuzilgan. VC9 VS 2008, VC11 - Visual Studio 2012 da kompilyatsiya qilinganda olinadi. Shunga ko'ra, bularning barchasi siz uchun ishlashi uchun kompyuteringizda kutubxonalar o'rnatilgan bo'lishi kerak. Visual Studio uchun qayta taqsimlanadigan Visual C++ tegishli yil. Bu masala bo'yicha ba'zi tushuntirishlar.

Bundan tashqari, agar sizning veb-serveringiz apache.org dan eski Apache bo'lsa, unda siz PHP ning VC6 versiyasini yuklab olishingiz kerak, uni tuzish uchun Visual Studio 6 dan foydalanilgan bo'lsa, PHP IIS uchun yoki yangi Apache bilan birgalikda ishlaydi , keyin siz zamonaviyroq narsalarni to'plashingiz mumkin;)

Men uchun tanlashda asosiy to'siq - bu mezbon. Endi PHP 5.5.4 ning barqaror versiyasi mavjud, ammo u hali ham 5.2.17 ga ega!

Endi eng qiziqarli qism: " ip xavfsiz yoki ipsiz xavfsizmi?"
Maqolaning bepul tarjimasi (Dominik Rayan, 27.09.2007)

Men hech qachon bunday buzilgan ingliz tilini ko'rmaganman:((Men maqolani tezda tarjima qilmoqchi bo'ldim, lekin muallif nima yozganini tushunishda qiynalib qoldim. "What-is-that" va murakkab jumlalar o'rtasidagi doimiy o'tishlar, odatda, Moskvani ajratib turadi. Rus tili bir xil murakkab, chunki men rus tilida biror narsani to'g'ri chaqirish bo'yicha etarli bilim va tasavvurga ega emasman, odatda faqat ingliz tilida yoziladi%) Masalan, men "ko'p jarayonli arxitektura" texnik tushunchasini hech qachon ko'rmaganman. rus tilida, lekin mening marvaridim "flow- unsafe" - bu umuman aqlli savol. Umuman olganda, men sizga nima bo'lganini aytib beraman.

O'rtasidagi farq ip xavfsiz Va ipsiz xavfsiz PHP ikkilik paketlari

PHP birinchi marta Windows tizimida 2000-yil 20-oktabrda PHP 3.0.17 bilan paydo bo‘lganidan beri uning ikkilik paketlari har doim shunday tuzilgan. ip xavfsiz (TS). Buning sababi quyidagicha: Windows ko'p tarmoqli arxitekturadan foydalanadi va Nix tizimlari ko'p jarayonli arxitekturani qo'llab-quvvatlaydi. Agar PHP ko'p bosqichli emas, balki ko'p jarayonli CGI ilovasi sifatida tuzilgan bo'lsa, uni IIS serverida Windows ostida CGI moduli sifatida ishlatish jiddiy sekinlashuvlarga va protsessordan foydalanishga olib keladi. Boshqa tomondan, siz PHP ni IIS ga ISAPI moduli sifatida ulashingiz mumkin ( ko'p tarmoqli qurilish talab qilinadi- taxminan. tarjimon). Keyin yana bir muammo paydo bo'ladi: ba'zi mashhur PHP kengaytmalari Unix/Linux-ni hisobga olgan holda ishlab chiqilgan, ya'ni. ko'p jarayonli arxitekturaga ega, bu esa IIS ga ISAPI moduli sifatida ulangan PHP ning ishdan chiqishiga olib keladi. Bu. CGI yaratish IISda PHP uchun eng barqaror muhit bo'lib, asosiy kamchiligi bu juda sekin. Har safar so'rov bo'lganda biz butun PHP muhitini xotiradan yuklashimiz va tushirishimiz kerak.

O'sha paytda IISda PHP ish faoliyatini yaxshilash uchun bir nechta variant mavjud edi. Birinchisi, PHP skriptlarini diskda va/yoki xotirada qisman kompilyatsiya qilingan holatda saqlaydigan eAccelerator kabi dasturlar bilan opcode keshlashdan foydalanish. Ushbu yondashuv skriptni bajarish vaqtini sezilarli darajada qisqartiradi. Boshqa variant esa IIS ni PHP rejimida ishlatish uchun sozlash edi FastCGI. Bunday holda, PHP jarayoni tugallangandan keyin yopilmadi, lekin keyingi PHP so'rovi bilan yangi vazifani oldi. Bundan tashqari, bir vaqtning o'zida bir nechta PHP jarayonlarini ishga tushirish mumkin bo'ldi, bu so'rovlarni qayta ishlashni sezilarli darajada tezlashtirdi, bu PHP CGI rejimining bonusi edi. Biroq, PHP kengaytmalari bilan kichik moslik muammolari bo'lishi mumkin. Bu hali ham PHP-dan foydalanishning eng tezkor usuli bo'lib, IIS Aid PHP o'rnatuvchisi buni amalga oshirish uchun sozlangan.

Ikkilik faylda yig'ilgan ip-xavfsiz rejimi (ip xavfsiz emas, NTS), sizga IIS (va Windows-dagi boshqa veb-serverlar) ni PHP-dan standart CGI interfeysi sifatida foydalanish uchun sozlash imkonini beradi, chunki unumdorlikni oshiradi. bu holda (bunday tuzilishda) PHP jarayoni iplarni sinxronlashtirishni kutish shart emas. Standart CGI interfeysi sifatida IISda "thread safe" va "no thread safe" PHP ikkilik paketlarining ishlashini taqqoslaganda, unumdorlik 40% gacha oshadi, ammo bu FastCGI usulida opcode ishlatish kabi tez emas. . Va eng katta muammo shundaki, siz ish zarralari xavfsiz bo'lmagan ikkilik fayllardan ishonchli tarzda foydalana olmaysiz. Bu shuni anglatadiki, siz xavfsiz bo'lmagan ikkilik paketlar (yozish vaqtida to'g'ri bo'lgan bayonot) tomonidan yaratilgan PHP muhitida eAccelerator kabi opcode keshlash tizimlaridan foydalana olmaysiz.

Agar ip-xavfsiz PHP-ni tarmoqli xavfsiz muhit bilan bir xil tezlikda sozlash imkoni bo'lmasa, unda nima uchun bunday tuzilishda kerak? Keling, FastCGI va Microsoftning so'nggi bir necha yil ichida ushbu sohadagi ishlanmalariga qaytaylik. Kichik yumshoq koderlar FastCGI-ning o'z versiyasini yaratdilar, bu sizga FastCGI rejimida xavfli PHP ikkiliklarini sozlash imkonini beradi, bu esa ishlashni yorug'lik tezligiga olib keladi :)

Maqolada men tormozlar faqat IIS veb-serverida foydalanilganda kuzatiladi degan xulosaga keldim. Qanday bo'lmasin, men Windows + Apache ostida hech qanday ahmoqona narsalarni ko'rmadim. Shuningdek, siz NTS yig'ilishini haddan tashqari oshirib yuborishingiz mumkinligini aytadi har qanday veb-server, lekin men bunday Apache konfiguratsiyasini tasavvur qila olmayman.

Men yaqinda pthreadlarni sinab ko'rdim va juda hayratda qoldim - bu PHPda bir nechta haqiqiy mavzular bilan ishlash qobiliyatini qo'shadigan kengaytma. Na taqlid, na sehr, na soxta - hamma narsa haqiqiy.



Men bunday vazifani o'ylayapman. Tezda bajarilishi kerak bo'lgan vazifalar to'plami mavjud. PHP da bu muammoni hal qilish uchun boshqa vositalar mavjud, ular bu yerda tilga olinmagan, maqola pthreadlar haqida.



Pthreads nima

Ana xolos! Xo'sh, deyarli hamma narsa. Darhaqiqat, qiziquvchan o'quvchini xafa qiladigan narsa bor. Bularning hech biri standart variantlar bilan tuzilgan standart PHP da ishlamaydi. Ko'p ish zarralaridan bahramand bo'lish uchun PHP-da ZTS (Zend Thread Safety) yoqilgan bo'lishi kerak.

PHP o'rnatish

Keyingi, ZTS bilan PHP. ZTSsiz PHP (37,65 va 265,05 soniya) bilan solishtirganda bajarilish vaqtining katta farqiga e'tibor bermang, men PHP sozlamalarini umumlashtirishga urinmadim. ZTS bo'lmagan holatda, masalan, menda XDebug yoqilgan.


Ko'rib turganingizdek, 2 ta ipdan foydalanganda dasturni bajarish tezligi chiziqli kodga qaraganda taxminan 1,5 baravar yuqori. 4 ta ipdan foydalanganda - 3 marta.


Shuni ta'kidlash mumkinki, protsessor 8 yadroli bo'lsa ham, agar 4 dan ortiq ip ishlatilgan bo'lsa, dasturning ishlash vaqti deyarli o'zgarmagan. Bu mening protsessorimda 4 ta jismoniy yadroga ega bo'lganligi sababli, men lavhani diagramma shaklida tasvirlab berdim.


Xulosa

PHP da pthreads kengaytmasi yordamida ko'p ish zarralari bilan juda oqlangan ishlash mumkin. Bu hosildorlikning sezilarli o'sishini ta'minlaydi.

Teglar: teglar qo'shish