برنامه نویسی چند رشته ای در PHP با استفاده از ترجمه Pthreads. محاسبات چند رشته ای در PHP: pthreads Path of the Jedi - با استفاده از پسوند PCNTL

من اخیراً pthread ها را امتحان کردم و به طرز خوشایندی شگفت زده شدم - این افزونه ای است که توانایی کار با چندین رشته واقعی را در PHP اضافه می کند. بدون تقلید، بدون جادو، بدون تقلبی - همه چیز واقعی است.



من چنین وظیفه ای را در نظر دارم. مجموعه ای از وظایف وجود دارد که باید به سرعت تکمیل شوند. PHP ابزارهای دیگری برای حل این مشکل دارد که در اینجا ذکر نشده است، مقاله در مورد pthread ها است.



thread ها چیست؟

همین! خوب، تقریباً همه چیز. در واقع، چیزی وجود دارد که ممکن است خواننده کنجکاو را ناراحت کند. هیچ کدام از اینها روی PHP استاندارد کامپایل شده با گزینه های پیش فرض کار نمی کند. برای لذت بردن از Multithreading، باید ZTS (Zend Thread Safety) را در PHP خود فعال کنید.

راه اندازی PHP

بعد، PHP با ZTS. به تفاوت زیاد در زمان اجرا در مقایسه با PHP بدون ZTS (37.65 در مقابل 265.05 ثانیه) اهمیت ندهید، من سعی نکردم تنظیمات PHP را تعمیم دهم. در مورد بدون ZTS، من برای مثال XDebug را فعال کرده ام.


همانطور که می بینید، هنگام استفاده از 2 رشته، سرعت اجرای برنامه تقریبا 1.5 برابر بیشتر از کد خطی است. هنگام استفاده از 4 رشته - 3 بار.


می توانید توجه داشته باشید که با وجود اینکه پردازنده 8 هسته ای است، در صورت استفاده از بیش از 4 رشته، زمان اجرای برنامه تقریباً بدون تغییر باقی می ماند. به نظر می رسد این به دلیل این است که پردازنده من دارای 4 هسته فیزیکی است، برای وضوح صفحه را به صورت نمودار به تصویر کشیده ام.


خلاصه

در PHP می توان با استفاده از پسوند pthreads با چند رشته ای کاملاً زیبا کار کرد. این باعث افزایش قابل توجه بهره وری می شود.

برچسب ها: اضافه کردن برچسب

گاهی اوقات انجام چندین عمل به طور همزمان ضروری می شود، به عنوان مثال، بررسی تغییرات در یک جدول پایگاه داده و ایجاد تغییرات در دیگری. علاوه بر این، اگر یکی از عملیات (مثلاً بررسی تغییرات) زمان زیادی را صرف کند، بدیهی است که اجرای متوالی تعادل منابع را تضمین نمی کند.

برای حل این نوع مشکل، برنامه نویسی از multithreading استفاده می کند - هر عملیات در یک رشته جداگانه با مقدار تخصیص منابع قرار می گیرد و در داخل آن کار می کند. با این رویکرد، تمام وظایف به صورت جداگانه و مستقل انجام می شود.

اگرچه PHP از multithreading پشتیبانی نمی‌کند، اما روش‌های مختلفی برای شبیه‌سازی آن وجود دارد که در ادامه به آن‌ها پرداخته می‌شود.

1. اجرای چندین نسخه از اسکریپت - یک کپی در هر عملیات

//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"] == "make_me_happy") ( make_her_happy(); ) elseif ($_GET["thread"] == "make_me_rich" ) ( find_ather_one( ); )

هنگامی که این اسکریپت را بدون پارامتر اجرا می کنیم، به طور خودکار دو نسخه از خود را با شناسه های عملیات ("thread=make_me_happy" و "thread=make_me_rich") اجرا می کند که اجرای توابع لازم را آغاز می کند.

به این ترتیب ما به نتیجه مطلوب می رسیم - دو عملیات به طور همزمان انجام می شود - اما این، البته، چند رشته ای نیست، بلکه به سادگی یک عصا برای انجام وظایف به طور همزمان است.

2. Path of the Jedi - با استفاده از پسوند PCNTL

PCNTL افزونه ای است که به شما امکان می دهد به طور کامل با فرآیندها کار کنید. علاوه بر مدیریت، از ارسال پیام، بررسی وضعیت و تعیین اولویت ها نیز پشتیبانی می کند. اسکریپت قبلی با استفاده از PCNTL به این صورت است:

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

کاملا گیج کننده به نظر می رسد، بیایید خط به خط آن را مرور کنیم.

در خط اول، فرآیند جاری را "فشار" می کنیم (فشار، کپی کردن یک فرآیند با حفظ مقادیر همه متغیرها است)، و آن را به دو فرآیند (جریان و فرزند) که به صورت موازی اجرا می شوند تقسیم می کنیم.

برای اینکه بفهمیم در حال حاضر در فرآیند فرزند هستیم یا مادر، تابع pcntl_fork 0 را برای فرزند و شناسه فرآیند را برای مادر برمی‌گرداند. بنابراین، در خط دوم، به $pid نگاه می کنیم، اگر صفر باشد، در فرآیند فرزند هستیم - ما در حال اجرای تابع هستیم، در غیر این صورت، در مادر (خط 4) هستیم، سپس یک فرآیند دیگر ایجاد می کنیم و به طور مشابه وظیفه را انجام دهد.

فرآیند اجرای اسکریپت:

بنابراین، اسکریپت 2 پردازش فرزند دیگر ایجاد می کند که کپی های آن هستند و شامل متغیرهای مشابه با مقادیر مشابه هستند. و با استفاده از شناسه برگردانده شده توسط تابع pcntl_fork متوجه می شویم که در حال حاضر در کدام رشته قرار داریم و اقدامات لازم را انجام می دهیم.

به نظر می رسد که توسعه دهندگان PHP به ندرت از همزمانی استفاده می کنند. من در مورد سادگی کد همزمان صحبت نمی‌کنم؛ البته برنامه‌نویسی تک رشته‌ای ساده‌تر و واضح‌تر است، اما گاهی اوقات استفاده کمی از موازی‌سازی می‌تواند عملکرد قابل توجهی را افزایش دهد.

در این مقاله نگاهی خواهیم داشت به اینکه چگونه می توان با استفاده از پسوند pthreads در PHP به multithreading دست یافت. برای این کار باید نسخه ZTS (Zend Thread Safety) PHP 7.x به همراه پسوند pthreads v3 نصب شده باشد. (در زمان نگارش، در PHP 7.1، کاربران باید از شاخه اصلی در مخزن pthreads نصب کنند - پسوند شخص ثالث را ببینید.)

یک توضیح کوچک: pthreads v2 برای PHP 5.x در نظر گرفته شده است و دیگر پشتیبانی نمی شود، pthreads v3 برای PHP 7.x است و به طور فعال در حال توسعه است.

پس از چنین انحرافی، مستقیماً به سر اصل مطلب می رویم!

پردازش وظایف یکباره

گاهی اوقات شما می خواهید وظایف یک بار مصرف را به روشی چند رشته ای پردازش کنید (به عنوان مثال، اجرای برخی وظایف I/O-Bound). در چنین مواردی، می‌توانید از کلاس Thread برای ایجاد یک رشته جدید و اجرای برخی پردازش‌ها در یک رشته جداگانه استفاده کنید.

مثلا:

$task = کلاس جدید Thread را گسترش می‌دهد ($response خصوصی؛ اجرای تابع عمومی() ($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"

در اینجا متد run پردازش ما است که در داخل یک رشته جدید اجرا می شود. هنگامی که Thread::start فراخوانی می شود، یک نخ جدید ایجاد می شود و متد run فراخوانی می شود. سپس با فراخوانی Thread::join thread فرزند را به رشته اصلی متصل می کنیم، که تا زمانی که رشته فرزند به پایان برسد مسدود می شود. این تضمین می کند که اجرای کار قبل از چاپ نتیجه (که در $task->response ذخیره می شود) به پایان می رسد.

ممکن است مطلوب نباشد که یک کلاس را با مسئولیت های اضافی مرتبط با منطق جریان (از جمله مسئولیت تعریف روش اجرا) آلوده کنیم. ما می توانیم چنین کلاس هایی را با ارث بردن آنها از کلاس Threaded تشخیص دهیم. سپس آنها را می توان در یک رشته دیگر اجرا کرد:

Class Task Threaded را گسترش می دهد ($response عمومی; تابع عمومی someWork() ($content = file_get_contents("http://google.com"); preg_match("~ (.+) ~", $content, $matches)؛ $ this->response = $matches; ) ) $task = وظیفه جدید; $thread = new class($task) Thread را گسترش می دهد ($task خصوصی؛ تابع عمومی __construct(Threaded $task) ($this->task = $task; ) تابع عمومی run() ($this->task->someWork( );))) $thread->start() && $thread->join(); var_dump($task->response);

هر کلاسی که باید در یک موضوع جداگانه اجرا شود بایداز کلاس Threaded به ارث می برد. زیرا قابلیت های لازم برای انجام پردازش روی رشته های مختلف و همچنین امنیت ضمنی و رابط های مفید (مانند همگام سازی منابع) را فراهم می کند.

بیایید به سلسله مراتب کلاس ارائه شده توسط پسوند pthreads نگاهی بیندازیم:

Threaded (قابل عبور، جمع آوری) Thread Worker Volatile Pool را اجرا می کند

ما قبلاً اصول کلاس‌های Thread و Threaded را پوشش داده‌ایم و یاد گرفته‌ایم، حالا بیایید به سه مورد دیگر (Worker، Volatile و Pool) نگاهی بیندازیم.

استفاده مجدد از موضوعات

شروع یک موضوع جدید برای هر کاری که باید موازی شود بسیار گران است. این به این دلیل است که برای دستیابی به multithreading در PHP باید یک معماری مشترک-هیچ در pthread ها پیاده سازی شود. به این معنی که کل زمینه اجرای نمونه فعلی مفسر PHP (شامل هر کلاس، رابط، صفت و تابع) باید برای هر رشته ایجاد شده کپی شود. از آنجا که این تأثیر عملکرد قابل توجهی دارد، جریان همیشه باید در صورت امکان دوباره مورد استفاده قرار گیرد. نخ ها به دو صورت قابل استفاده مجدد هستند: استفاده از Workers یا استفاده از Pools.

کلاس Worker برای انجام تعدادی کار به صورت همزمان در یک رشته دیگر استفاده می شود. این کار با ایجاد یک نمونه Worker جدید (که یک رشته جدید ایجاد می کند) و سپس فشار دادن وظایف به پشته آن رشته جداگانه (با استفاده از Worker::stack) انجام می شود.

در اینجا یک مثال کوچک وجود دارد:

Class Task Threaded را گسترش می دهد ($value خصوصی؛ تابع عمومی __construct(int $i) ($this->value = $i; ) عملکرد عمومی run() (usleep(250000); echo "Task: ($this->value) \n"; ) ) $worker = new Worker(); $worker->start(); for ($i = 0; $i stack(new Task($i)); ) while ($worker->collect()); $worker-> shutdown();

در مثال بالا، 15 کار برای یک شی $worker جدید از طریق متد Worker::stack روی پشته فشار داده می شوند و سپس به ترتیبی که فشار داده شده اند پردازش می شوند. روش Worker::collect، همانطور که در بالا نشان داده شده است، برای پاکسازی وظایف به محض اتمام اجرا استفاده می شود. با آن، در داخل یک حلقه while، رشته اصلی را مسدود می کنیم تا زمانی که تمام وظایف روی پشته تکمیل و پاک شوند - قبل از اینکه Worker::shutdown را فراخوانی کنیم. خاتمه دادن زودهنگام یک کارگر (یعنی در زمانی که هنوز کارهایی برای تکمیل وجود دارد) همچنان رشته اصلی را مسدود می کند تا زمانی که همه کارها اجرای خود را کامل کنند، فقط به این دلیل که کارها زباله جمع آوری نمی شوند (که مستلزم نشت حافظه است).

کلاس Worker چندین روش دیگر مربوط به پشته وظیفه خود را ارائه می دهد، از جمله Worker::unstack برای حذف آخرین وظیفه انباشته شده و Worker::getStacked برای دریافت تعداد وظایف در پشته اجرا. پشته یک کارگر فقط شامل وظایفی است که باید اجرا شوند. هنگامی که یک کار در پشته کامل شد، حذف می شود و در یک پشته جداگانه (داخلی) برای جمع آوری زباله (با استفاده از روش Worker::collect) قرار می گیرد.

راه دیگر برای استفاده مجدد از یک نخ در چندین کار، استفاده از یک Thread Pool (از طریق کلاس Pool) است. یک Thread Pool از گروهی از Workers برای فعال کردن وظایف استفاده می کند همزمان، که در آن ضریب همزمانی (تعداد رشته های استخری که با آنها کار می کند) هنگام ایجاد استخر تنظیم می شود.

بیایید مثال بالا را برای استفاده از مجموعه ای از کارگران تطبیق دهیم:

Class Task Threaded را گسترش می دهد ($value خصوصی؛ تابع عمومی __construct(int $i) ($this->value = $i; ) عملکرد عمومی run() (usleep(250000); echo "Task: ($this->value) \n"; ) ) $pool = new Pool(4); برای ($i = 0؛ $i ارسال(کار جدید($i)); ) while ($pool->collect()); $pool-> shutdown();

چند تفاوت قابل توجه هنگام استفاده از استخر در مقایسه با کارگر وجود دارد. اولاً، استخر نیازی به راه‌اندازی دستی ندارد؛ به محض در دسترس قرار گرفتن، اجرای آن‌ها را آغاز می‌کند. دوما ما ارسالوظایف به استخر، نه آنها را روی یک پشته قرار دهید. علاوه بر این، کلاس Pool از Threaded ارث نمی برد و بنابراین نمی تواند به رشته های دیگر منتقل شود (برخلاف Worker).

این یک تمرین خوب برای کارگران و استخرها است که همیشه به محض اتمام کارهای خود را تمیز کنند و سپس خودشان به صورت دستی آنها را خاتمه دهند. رشته هایی که با استفاده از کلاس Thread ایجاد می شوند نیز باید به رشته اصلی متصل شوند.

thread ها و (un)mutability

آخرین کلاسی که به آن خواهیم پرداخت، Volatile است، یک افزوده جدید به pthreads v3. تغییر ناپذیری به یک مفهوم مهم در pthread ها تبدیل شده است زیرا بدون آن، عملکرد به طور قابل توجهی آسیب می بیند. بنابراین، به طور پیش‌فرض، ویژگی‌های کلاس‌های Threaded که خود اشیاء Threaded هستند، اکنون غیرقابل تغییر هستند و بنابراین نمی‌توان آنها را پس از انتساب اولیه بازنویسی کرد. تغییرپذیری صریح برای چنین ویژگی هایی در حال حاضر ترجیح داده می شود و هنوز هم می توان با استفاده از کلاس جدید Volatile به دست آورد.

بیایید به مثالی نگاه کنیم که محدودیت‌های تغییرناپذیری جدید را نشان می‌دهد:

Class Task Threaded // یک کلاس Threaded را گسترش می دهد ( تابع عمومی __construct() ($this->data = new Threaded(); // $this->داده قابل رونویسی نیست، زیرا یک ویژگی Threaded از یک کلاس Threaded است) ) $task = class new(new Task()) Thread ( // یک کلاس Threaded را گسترش می دهد، زیرا Thread تابع عمومی Threaded را گسترش می دهد __construct($tm) ($this->threadedMember = $tm؛ var_dump($this->threadedMember-> داده)؛ // object(Threaded)#3 (0) () $this->threadedMember = new StdClass(); // نامعتبر است، زیرا ویژگی عضو Threaded یک کلاس Threaded است ) );

از سوی دیگر، ویژگی‌های رشته‌ای کلاس‌های Volatile قابل تغییر هستند:

Class Task Volatile را گسترش می دهد ( تابع عمومی __construct() ($this->data = new Threaded(); $this->data = new StdClass(); // معتبر است، زیرا ما در یک کلاس فرار هستیم) ) $task = new class(new Task()) Thread را گسترش می دهد ( تابع عمومی __construct($vm) ($this->volatileMember = $vm; var_dump($this->volatileMember->data); // object(stdClass)#4 (0) () // هنوز نامعتبر است، از آنجایی که Volatile Threaded را گسترش می دهد، بنابراین ویژگی همچنان یک عضو Threaded از کلاس Threaded است $this->volatileMember = new StdClass(); ) );

می بینیم که کلاس Volatile تغییرناپذیری تحمیل شده توسط کلاس Threaded والد را لغو می کند تا توانایی تغییر خصوصیات Threaded (و همچنین unset()) را فراهم کند.

موضوع بحث دیگری برای پوشش موضوع متغیر و کلاس فرار وجود دارد - آرایه ها. در pthread ها، آرایه ها به طور خودکار به اشیاء Volatile فرستاده می شوند که به ویژگی های کلاس Threaded اختصاص داده شوند. این به این دلیل است که دستکاری آرایه ای از زمینه های متعدد PHP به سادگی ایمن نیست.

برای درک بهتر برخی موارد، دوباره به یک مثال نگاه می کنیم:

آرایه $ = ; $task = new class($array) Thread را گسترش می دهد ($data خصوصی؛ تابع عمومی __construct(array $array) ($this->data = $array; ) تابع عمومی run() ($this->data = 4; $ this->data = 5; print_r($this->data); ) ); $task->start() && $task->join(); /* خروجی: شی فرار ( => 1 => 2 => 3 => 4 => 5) */

می‌بینیم که اشیاء فرار را می‌توان به‌گونه‌ای رفتار کرد که انگار آرایه هستند، زیرا از عملیات آرایه‌ای مانند (همانطور که در بالا نشان داده شده است) عملگر ()subset را پشتیبانی می‌کنند. با این حال، کلاس های فرار از توابع پایه آرایه مانند array_pop و array_shift پشتیبانی نمی کنند. در عوض، کلاس Threaded چنین عملیاتی را به عنوان متدهای داخلی در اختیار ما قرار می دهد.

به عنوان یک نمایش:

$data = کلاس جدید گسترش می یابد Volatile ( public $a = 1; public $b = 2; public $c = 3; ); var_dump ($data); var_dump($data->pop()); var_dump($data->shift()); var_dump ($data); /* خروجی: object(class@anonymous)#1 (3) ( ["a"]=> int(1) ["b"]=> int(2) ["c"]=> int(3)) int(3) int(1) object(class@anonymous)#1 (1) ( ["b"]=> int(2) ) */

سایر عملیات های پشتیبانی شده عبارتند از Threaded::chunk و Threaded::merge.

هماهنگ سازی

در بخش آخر این مقاله به همگام سازی در pthread ها خواهیم پرداخت. همگام سازی روشی است که به شما امکان می دهد دسترسی به منابع مشترک را کنترل کنید.

به عنوان مثال، بیایید یک شمارنده ساده پیاده سازی کنیم:

$counter = کلاس جدید Thread را گسترش می دهد ( public $i = 0; public function run() ( for ($i = 0; $i i; ) ) ); $counter->start(); برای ($i = 0; $i i; ) $counter->join(); var_dump($counter->i); // عددی از 10 تا 20 را چاپ می کند

بدون استفاده از همگام سازی، خروجی قطعی نیست. چندین رشته بدون دسترسی کنترل شده روی یک متغیر می نویسند، که به این معنی است که به روز رسانی ها از بین خواهند رفت.

بیایید این را حل کنیم تا با اضافه کردن زمان، خروجی صحیح 20 را بدست آوریم:

$counter = کلاس جدید Thread را گسترش می دهد ( public $i = 0; public function run() ( $this->synchronized(function () ( for ($i = 0; $i i; ) )); ) ); $counter->start(); $counter->synchronized(function ($counter) ( for ($i = 0; $i i; ) ), $counter); $counter->join(); var_dump($counter->i); // int(20)

بلوک‌های کد همگام‌سازی شده نیز می‌توانند با استفاده از روش‌های Threaded::wait و Threaded::notify (یا Threaded::notifyAll) با یکدیگر ارتباط برقرار کنند.

در اینجا یک افزایش متناوب در دو حلقه همزمان همزمان وجود دارد:

$counter = کلاس جدید Thread را گسترش می دهد ( عمومی $cond = 1; تابع عمومی run() ($this->synchronized(function () ( برای ($i = 0; $i notify(); if ($this->cond === 1) ($this->cond = 2; $this->wait(); ) ))); ) ); $counter->start(); $counter->synchronized(function ($counter) ( if ($counter->cond !== 2) ( $counter->wait(); // منتظر بمانید تا دیگری اول شروع شود ) برای ($i = 10; $i notify(); if ($counter->cond === 2) ( $counter->cond = 1; $counter->wait(); ) ) ), $counter); $counter->join(); /* خروجی: 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 قرار گرفته است. این شرایط حیاتی هستند زیرا به تماس همگام‌سازی شده اجازه می‌دهند زمانی که اعلان دریافت کرد و شرایط مشخص شده درست است، از سر گرفته شود. این مهم است زیرا اعلان‌ها می‌توانند از مکان‌هایی غیر از زمانی که Threaded::notify فراخوانی می‌شود ارسال شود. بنابراین، اگر فراخوانی های متد Threaded::wait در شرایط محصور نشده باشد، اجرا خواهیم کرد. بیدار شدن نادرست، که منجر به رفتار کد غیرقابل پیش بینی می شود.

نتیجه

ما به پنج کلاس بسته pthreads (Threaded، Thread، Worker، Volatile و Pool) و نحوه استفاده از هر کلاس نگاه کردیم. ما همچنین نگاهی به مفهوم جدید تغییرناپذیری در pthread ها انداختیم و مروری کوتاه بر قابلیت های همگام سازی پشتیبانی شده ارائه کردیم. با وجود این اصول اولیه، اکنون می‌توانیم شروع به بررسی نحوه استفاده از pthread در موارد دنیای واقعی کنیم! این موضوع پست بعدی ما خواهد بود.

اگر به ترجمه پست بعدی علاقه دارید به من اطلاع دهید: در شبکه های اجتماعی نظر دهید. شبکه ها، رای مثبت دهید و پست را با همکاران و دوستان خود به اشتراک بگذارید.

  • برنامه نويسي،
  • برنامه نویسی موازی
  • من اخیراً pthread ها را امتحان کردم و به طرز خوشایندی شگفت زده شدم - این افزونه ای است که توانایی کار با چندین رشته واقعی را در PHP اضافه می کند. بدون تقلید، بدون جادو، بدون تقلبی - همه چیز واقعی است.



    من چنین وظیفه ای را در نظر دارم. مجموعه ای از وظایف وجود دارد که باید به سرعت تکمیل شوند. PHP ابزارهای دیگری برای حل این مشکل دارد که در اینجا ذکر نشده است، مقاله در مورد pthread ها است.



    thread ها چیست؟

    همین! خوب، تقریباً همه چیز. در واقع، چیزی وجود دارد که ممکن است خواننده کنجکاو را ناراحت کند. هیچ کدام از اینها روی PHP استاندارد کامپایل شده با گزینه های پیش فرض کار نمی کند. برای لذت بردن از Multithreading، باید ZTS (Zend Thread Safety) را در PHP خود فعال کنید.

    راه اندازی PHP

    بعد، PHP با ZTS. به تفاوت زیاد در زمان اجرا در مقایسه با PHP بدون ZTS (37.65 در مقابل 265.05 ثانیه) اهمیت ندهید، من سعی نکردم تنظیمات PHP را تعمیم دهم. در مورد بدون ZTS، من برای مثال XDebug را فعال کرده ام.


    همانطور که می بینید، هنگام استفاده از 2 رشته، سرعت اجرای برنامه تقریبا 1.5 برابر بیشتر از کد خطی است. هنگام استفاده از 4 رشته - 3 بار.


    می توانید توجه داشته باشید که با وجود اینکه پردازنده 8 هسته ای است، در صورت استفاده از بیش از 4 رشته، زمان اجرای برنامه تقریباً بدون تغییر باقی می ماند. به نظر می رسد این به دلیل این است که پردازنده من دارای 4 هسته فیزیکی است، برای وضوح صفحه را به صورت نمودار به تصویر کشیده ام.


    خلاصه

    در PHP می توان با استفاده از پسوند pthreads با چند رشته ای کاملاً زیبا کار کرد. این باعث افزایش قابل توجه بهره وری می شود.

    برچسب ها:

    • php
    • نخ ها
    افزودن برچسب

    من اخیراً pthread ها را امتحان کردم و به طرز خوشایندی شگفت زده شدم - این افزونه ای است که توانایی کار با چندین رشته واقعی را در PHP اضافه می کند. بدون تقلید، بدون جادو، بدون تقلبی - همه چیز واقعی است.



    من چنین وظیفه ای را در نظر دارم. مجموعه ای از وظایف وجود دارد که باید به سرعت تکمیل شوند. PHP ابزارهای دیگری برای حل این مشکل دارد که در اینجا ذکر نشده است، مقاله در مورد pthread ها است.



    thread ها چیست؟

    همین! خوب، تقریباً همه چیز. در واقع، چیزی وجود دارد که ممکن است خواننده کنجکاو را ناراحت کند. هیچ کدام از اینها روی PHP استاندارد کامپایل شده با گزینه های پیش فرض کار نمی کند. برای لذت بردن از Multithreading، باید ZTS (Zend Thread Safety) را در PHP خود فعال کنید.

    راه اندازی PHP

    بعد، PHP با ZTS. به تفاوت زیاد در زمان اجرا در مقایسه با PHP بدون ZTS (37.65 در مقابل 265.05 ثانیه) اهمیت ندهید، من سعی نکردم تنظیمات PHP را تعمیم دهم. در مورد بدون ZTS، من برای مثال XDebug را فعال کرده ام.


    همانطور که می بینید، هنگام استفاده از 2 رشته، سرعت اجرای برنامه تقریبا 1.5 برابر بیشتر از کد خطی است. هنگام استفاده از 4 رشته - 3 بار.


    می توانید توجه داشته باشید که با وجود اینکه پردازنده 8 هسته ای است، در صورت استفاده از بیش از 4 رشته، زمان اجرای برنامه تقریباً بدون تغییر باقی می ماند. به نظر می رسد این به دلیل این است که پردازنده من دارای 4 هسته فیزیکی است، برای وضوح صفحه را به صورت نمودار به تصویر کشیده ام.


    خلاصه

    در PHP می توان با استفاده از پسوند pthreads با چند رشته ای کاملاً زیبا کار کرد. این باعث افزایش قابل توجه بهره وری می شود.



    
    بالا