PHP RFC inayofafanua Polling API asilia imepitishwa na kuunganishwa kwenye tawi kuu (master branch) la lugha hiyo, ikitoa njia ya haraka kwa watengenezaji (developers) ya kiwango cha OS ya kufanya polling ya file descriptors. Ikiwa imeunganishwa na Fibers zilizoongezwa hivi karibuni, PHP sasa ina msingi wa ndani na wenye ufanisi kwa kodi za asynchronous—pengo ambalo kwa muda mrefu limewalazimu maktaba (libraries) kutengeneza njia zao mbadala.

Fibers na event loop, zilizotenganishwa

Fibers ni msingi wa kiwango cha chini wa mtiririko wa udhibiti (control-flow primitive). Zinaruhusu kazi (function) kusitisha utekelezaji wake katika hatua iliyochaguliwa na baadaye kuendelea pale ilipoishia. Jambo la muhimu ni kwamba, fiber haijui chochote kuhusu sockets, timers au chanzo kingine chochote cha I/O; inasimama tu na kuanza upya kulingana na mahitaji.

Event loop ni ratiba (scheduler) inayofanya maamuzi ya ni lini fiber iliyositishwa inapaswa kuendelezwa. Katika mfumo wa kawaida wa async, loop hufuatilia seti ya file descriptors, inasubiri ziweze kusomwa au kuandikwa, na kisha huamsha fiber inayohusika.

Hapo awali PHP ilikuwa na Fibers lakini ilikosa utaratibu asilia wa kuuliza mfumo wa uendeshaji (operating system) ni descriptors zipi zilizo tayari. Matokeo yake yalikuwa ni utegemezi wa stream_select() au extensions za nje, na kila maktaba ya async iliishia kuandika mifumo yake ya nyuma (back-ends) kwa ajili ya epoll ya Linux, kqueue ya BSD, IOCP ya Windows, n.k.

Polling API mpya inaziba pengo hilo. Inatoa kizuizi chepesi (thin wrapper) kuzunguka vifaa vya polling vya OS (epoll kwenye Linux, kqueue kwenye BSD/macOS, n.k.). API hii haichukui nafasi ya Fibers; inampa event loop tu kasi na uwezo wa kukua (scalability) unaohitaji.

Kwa nini mabadiliko haya ni muhimu kwa ReactPHP, Amp na marafiki zao

ReactPHP na Amp v3 zimejenga tabaka zao za uakisi (abstraction layers) juu ya mifumo ya polling ya OS. Tabaka hizo zina njia nyingi za kodi, kila moja ikiwa imerekebishwa kwa ajili ya jukwaa mahususi, na lazima ziende sambamba na mabadiliko ya kernel. Kwa Polling API asilia, maktaba zinaweza kuacha sehemu kubwa ya mifumo hiyo na kutegemea mwito mmoja (single call) unaotolewa na kiini (core).

  • Matengenezo – Matawi machache ya jukwaa mahususi yanamaanisha hitilafu (bugs) chache na eneo dogo la ukaguzi wa usalama.
  • Utendaji – Mwito asilia huwasiliana moja kwa moja na epoll/kqueue.
  • Uhamishaji (Portability) – Kodi inayofanya kazi kwenye PHP ya kawaida ("vanilla") sasa inapata utendaji uleule wa msingi kwenye mifumo yote ya uendeshaji inayoungwa mkono, bila kuhitaji extensions za hiari.

Kwa upande mwingine, Swoole inabaki kuwa mbadala kamili wa runtime inayokuja na event loop na mfumo wake wa coroutine. Polling API haiongezi athari kwa chaguzi za Swoole; watengenezaji wanaohitaji latency ya chini sana au usimamizi wa kumbukumbu wa kipekee bado wataichukulia kama chaguo tofauti.

Jaribio la utendaji (benchmark) la haraka linaonyesha ukweli

Ratiba (scheduler) ya chini kabisa ilichukua URL kadhaa kupitia raw sockets, ikitumia Io\Poll\Context moja kusimamia fiber nyingi. Machambo mawili yalitokea:

  1. Kasi – Kuongeza maombi mengi ya wakati mmoja hakiongezi muda wote uliopita; kundi la maombi huisha haraka kama ombi moja la polepole zaidi. Kwa maneno mengine, mzigo wa uendeshaji wa pamoja (concurrency overhead) ni sifuri kabisa.
  2. Gharama ya CPU – Kwa stream_select(), matumizi ya CPU hupanda kwa kuonekana wazi kadiri idadi ya streams inavyoongezeka, kwa sababu kazi hiyo lazima ipitie kila descriptor katika kila mwito. Gharama ya Polling API inabaki vilevile kutoka streams tatu hadi thambini, shukrani kwa uwezo wa kernel kufuatilia descriptors nyingi katika mwito mmoja wa mfumo.

Nini watengenezaji wanapaswa kufanya sasa

  • Tumia Amp v3 ikiwa unapendelea mtindo wa asilia wa fiber unaoendana moja kwa moja na API mpya. Kiolesura chake cha umma tayari kinaunganishwa na poller ya msingi, hivyo unapata faida hiyo bila kuandika upya kodi yako.
  • Endelea na ReactPHP ikiwa unapenda udhibiti wa wazi juu ya maisha ya loop (lifecycle).
  • Epuka ratiba (schedulers) za kipekee kwa kazi za uzalishaji (production). Usiandike ratiba yako mwenyewe kwa ajili ya uzalishaji.