PHP 8.1 Fibers Feature

31

martie 2021

PHP 8.1 Fibers Feature

De: Tree Web Solutions | Etichete: php 8.1, php 8.1 fibers feature, cum va functiona Fibers, php 8.1 noutati

PHP încearcă să îndepărteze lipsa de caracteristici din baza sa de cod, iar Fibers este una dintre adăugările semnificative ale limbajului. PHP Fibers , care intră în PHP 8.1 la sfârșitul anului, va introduce un fel de programare asincronă (coroutine) în sălbăticie.

Fibers Conceptul practic se referă la un fir ușor de execuție ( de asemenea , numit coroutine ). Acestea par să ruleze în paralel, dar în cele din urmă sunt gestionate de runtime în sine, mai degrabă decât prin împingerea acestuia direct către CPU. O mulțime de limbi majore au propriile lor modalități de a le implementa , dar principiul este același: lăsați computerul să facă două sau mai multe lucruri în același timp și să așteptați până când totul este finalizat.

Implementarea PHP a fibrelor nu este adevărată calcul asincron, așa cum se poate crede. Într-adevăr, nucleul PHP va fi încă sincron după introducerea fibrelor.

Vă puteți gândi la Fibrele PHP ca la trecerea de la o mașină la alta.

Un Fiber este o singură clasă finală care arată ca o mașină: poate porni și rula imediat, poate împinge frâna și aștepta și își poate relua călătoria.

final class Fiber 
{

public function __construct(callable $callback) {}
public function start(mixed ...$args): mixed {}
public function resume(mixed $value = null): mixed {}
public function throw(Throwable $exception): mixed {}
public function isStarted(): bool {}
public function isSuspended(): bool {}
public function isRunning(): bool {}
public function isTerminated(): bool {}
public function getReturn(): mixed {}
public static function this(): ?self {}
public static function suspend(mixed $value = null): mixed {}

}

Când creați o nouă instanță Fiber cu a callable, nu se va întâmpla nimic. Abia după ce porniți Fiber, callback-ul este executat ca orice alt cod PHP normal.

$ fiber = new Fiber (function (): void { 
echo "Execut o Fiber, da!";
});
$ fibra-> start (); // Rulez un Fiber, da!

Nu am spus că fibrele sunt asincrone? Ei sunt, dar numai până când dați frâna apelând Fiber::suspend()în interiorul apelului invers. Apoi trece controlul către „exterior”, dar rețineți că această mașină Fiber este încă în viață și așteaptă să reia.

$ fiber = new Fiber (function (): void { 
Fiber :: suspend ();
echo "Execut o Fiber, da!";
});
$ fibra-> start (); // [Nothing happens]

Acum, când mașina este suspendată, următorul lucru de făcut este să vă scoateți piciorul de pe frână și, pentru asta, putem apela resume()metoda din exterior.

$fiber = new Fiber(function() : void {
   Fiber::suspend();
   echo "I'm running a Fiber, yay!";
});
$fiber->start(); // [Nothing happened]
$fiber->resume(); // I'm running a Fiber, yay!

Acest lucru este literalmente asincron neadevărat, dar asta nu înseamnă că aplicația dvs. nu poate face două lucruri la un moment dat. Adevărul real aici este că starea funcției Fiber este salvată acolo unde a fost lăsată. Treceți în mod figurat între mașini, conducând fiecare la un punct.

Unul dintre lucrurile despre îngrijite start()suspend(și resume()este faptul că acestea acceptă argumente:

  • start()Metoda va trece Argumentarea callableși va reveni , indiferent de suspend()metoda primește.
  • La suspend()metoda returneaza orice valorizează resume()metoda primită.
  • În resume()metoda returneaza indiferent de apel de lângă suspend()primite.

Acest lucru face ca comunicarea dintre firul principal și fibra să fie relativ ușoară:

  • resume()este folosit pentru a pune valori în Fibre care sunt primite cu suspend()și
  • suspend()este folosit pentru a împinge valorile primite de resume().

Acest lucru face ca exemplul oficial să fie mai ușor de înțeles:

$fiber = new Fiber(function (): void {
    $value = Fiber::suspend('fiber');
    echo "Value used to resume fiber: ", $value, "\n";
});
 
$value = $fiber->start();
 
echo "Value from fiber suspending: ", $value, "\n";
 
$fiber->resume('test');

Dacă executați codul de mai sus, veți primi așa ceva:

Valoarea din suspendarea fibrelor: fibra 
Valoarea utilizată pentru reluarea fibrei: test

Să recunoaștem, PHP este asociat cu nginx / Apache 99% din timp, în principal pentru că nu este multithread. Serverul care vine în PHP se blochează și servește doar pentru unele teste sau pentru a arăta ceva unui client.

Fibrele pot deschide ușa pentru a lăsa PHP să funcționeze cu socketul mai eficient și să permită lucruri precum WebSockets, evenimente din partea serverului, conexiuni bazate pe baze de date sau chiar HTTP / 3, fără a fi nevoie să recurgeți la compilarea extensiilor, făcându-vă drumul în jos cu neintenționate , încapsulând PHP într-un alt timp de execuție extern sau în orice altă rețetă pentru dezastru.

Unele lucruri ar putea dura mult timp pentru a se stabili, dar dacă există promisiunea de a păstra o singură bază de cod pentru alte caracteristici, fără a fi nevoie să petrec zile încercând să compilați și să implementați, sunt la bord.

Conform documentației, Fibers oferă „doar minimul necesar pentru a permite codului utilizatorului să implementeze coroutine full-stack sau fire verzi în PHP”.

Cu alte cuvinte, cu excepția cazului în care aveți un motiv foarte ciudat pentru a le folosi direct, nu va trebui niciodată să interacționați cu fibrele, așa cum ați face coroutine pe Javascript sau Go.

Unele cadre de nivel înalt (cum ar fi Symfony , Laravel , CodeIgniter și CakePHP , printre altele) vor avea nevoie de ceva timp pentru a înțelege cum să abordeze Fibers și pentru a crea un set de instrumente cu care să lucreze din punctul de vedere al dezvoltatorului. Unele cadre de nivel scăzut, cum ar fi amphp și ReactPHP , au urcat deja pe nava Fiber în cele mai recente versiuni de dezvoltare.

În timp ce acest lucru vă va elibera să vă gândiți mai mult la fibre decât la ideea dvs., înseamnă că fiecare își va crea propria sa concurență, cu toate avantajele și avertismentele sale.

Îl voi cita pe Aaron Piotrowski din PHP Internals Podcast # 74 : „Întrucât numai o singură fibră poate fi executată în același timp, nu aveți aceleași condiții de rasă pe care le aveți cu memoria accesată sau scrisă de două fire în același timp.”

Aaron adaugă, de asemenea, că vor fi cadrele care vor putea aborda problema concurenței și sincronizării pe aceeași bucată de memorie.

Acest lucru este bun pentru că nu va trebui să vă gândiți la cursele de date, semaforele și mutele, lucruri pe care goferii le înțeleg perfect. Dar totuși ești obligat, în esență, doar două lucruri la un moment dat, indiferent de ceea ce faci.

Deoarece doar o singură fibră rulează în același timp, chiar dacă declarați mai multe, nu există nicio problemă de sincronizare a datelor. Dar Aaron a spus că există potențialul ca o altă fibră să se trezească și să rescrie ceea ce împarte prima fibră. Una dintre soluții este utilizarea stilului canalelor Go.

Derick Rethans a întrebat despre canale, iar răspunsul lui Aaron este simplu: altceva trebuie implementat alături de Fibers, dar până atunci, cadrele vor avea ultimul cuvânt despre modul de utilizare a canalelor, dacă le consideră necesare pentru ceea ce oferă, precum băieții la amphp .

Limba Go a câștigat din ce în ce mai mult din aceste luni, mai ales datorită faptului că a fost construită în jurul concurenței de la bază. Orice poate fi executat concomitent cu gocuvântul cheie, iar sincronizarea se face prin mutexe sau canale , ceea ce face ca moartea creierului să fie ușor de lucrat.

nume: = make (chan string)du-te doFoo (nume) 
du-te doBar (nume)

Din această perspectivă, Go este cu kilometri înaintea soluției inițiale de concurență PHP. Dacă aveți nevoie de ceva complet multithreaded, vă recomandăm să creați software-ul în Go sau chiar Rust dacă doriți să utilizați direct fire de procesare CPU.

Nu este faptul că PHP nu este compatibil cu niciun model de concurență, dar cu siguranță fundamentul său este încă sincron la bază, în detrimentul comodității și al înțelegerii mai bune. Comparativ cu Go, acesta din urmă suferă de instalații sanitare excesive .

Dacă doriți un model de concurență adevărat, cum ar fi Go, atunci PHP ar trebui să fie rescris de la bun început, dar asta ar deschide o mulțime de posibilități într-o lume a computerului care a îmbrățișat deja multithreading-ul.

Sursa: https://betterprogramming.pub

Distribuie această postare