# Asynchronous is the ability of a software system not to block the main thread of execution.
# An asynchronous operation is an operation that does not blocking flow execution of a program until it completes.
### Blocking operations ```[php] [|6] public function update(User $user) { try { $sql = 'UPDATE ...'; return $this->connection->execute($sql, $user->data()); } catch (\PDOException $error) { log($error->getMessage()); } return true; } ```
### Blocking operations * File operations (fwrite, file_get_contents) * Database interaction (PDOConnection, RedisClient) * Proceses (exec, system, proc_open) * stdin/stdout (readline, echo, print) * Timers (sleep, usleep)
### Non-blocking sql client v.0 ```[php] [|3|4|5|6|8] public function execAsync(string $query, array $params = []) { $socket = stream_socket_client('127.0.0.1:3306', ...); stream_set_blocking($socket, false); $data = $this->packBinarySQL($query, $params); socket_write($socket, $data, strlen($data)); // but what can we return? } ```

Promise

Promise

### Proof of Concept ```[php] interface Promise { const STATUS_PENDING = 0, STATUS_RESOLVED = 1, STATUS_REJECTED = 2; public function onResolve(callable $callback); public function onReject(callable $callback); public function resolve($data); public function reject(\Throwable $error); } ```

Deffered

### Non-blocking sql client v.1 ```[php] [8] public function execAsync(string $query, array $params = []) { $socket = stream_socket_client('127.0.0.1:3306', ...); stream_set_blocking($socket, false); $data = $this->packBinarySQL($query, $params); socket_write($socket, $data, strlen($data)); return $deferred->promise(); } ```
### Let's use it! ```[php] [|1|3-5|7-9] $promise = $this->execAsync($sql, $user->data()); $promise->onResolve(function (int $rows) { echo "Affected rows: {$rows}"; }); $promise->onReject(function (\Throwable $error) { log($error->getMessage()); }); ```
### Proof of concept for Event Loop ```[php] [|4|6-8|7|10] public static function run() { while (true) { stream_select($readSockets, $writeSockets, null, 0); foreach ($readSockets as $i => $socket) { call_user_func(self::readCallbacks[$i], $socket); } // Do same for write sockets } } ```
### Non-blocking sql client v.2 ```[php] [|5-7] public function execAsync(string $query, array $params = []) { $deferred = new Deferred; Loop::onReadable($socket, function ($socket) use ($deferred) { $deferred->resolve(socket_read($socket)); }); return $deferred->promise(); } ```
### Event loop can do: * Timer handling (setTimeout, setInterval. Hello JavaScript!) * Repeat and limit execution * Handle sys calls and process control

What do we have?

Library Supports Type Stars
ReactPHP 5.3+ Promise A 7.9k
amphp 7.0+ Coroutines 3.1k
Swoole 开发工 Coroutine Fiber 16.5k
Workerman 中文主 PCNTL Ext 9.1k
### Non-blocking sql client v.ReactPHP ```[php] [|5-7|8-10] $connection = (new ConnectionFactory)->createLazyConnection(); $promise = $connection->query('UPDATE...'); $promise->then( function (QueryResult $command) { echo count($command->resultRows) . ' row(s) in set.'; }, function (Exception $error) { echo 'Error: ' . $error->getMessage(); } ); ```
### Welcome to callback hell! ```[php] $promise ->then(function ($data) { return new Promise(...); }) ->then(function ($data) { ... }, function ($error) { log($error); }) ... ```

Hello, JavaScript, my old friend...

callback hell
### Non-blocking sql client v.amphp ```[php][|4] $pool = Mysql\pool("host=127.0.0.1 port=3306 db=test"); try { $result = yield $pool->query("UPDATE ..."); echo $result->affectedRows . ' row(s) in set.'; } catch (\Throwable $error) { echo 'Error: ' . $error->getMessage(); } ```

Yield

### Yield? Generators! ```[php][] function generator($counter = 1) { yield $counter++; echo "A"; yield $counter; echo "B"; yield ++$counter; } ``` ```[php][] foreach (generator(1) as $value) { echo $value; } ``` ```[php][] Output for 8.0.2 | took 17 ms, 17.05 MiB 1A2B3 ``` ```[php][] $generator = generator(1); while ($generator->valid()) { echo $generator->current(); $generator->next(); } ```
### Generators? Coroutines! ```[php][|2-4] function printer() { while (true) { echo yield; } } $print = printer(); $print->send('Hello'); $print->send(' Smartbox'); $print->send('!'); // Output for 8.0.2 | took 21 ms, 17.25 MiB // Hello Smatbox! ```
### Coroutines! ```[php][] function printer() { try { echo yield; } catch (\Throwable $e) { echo $e->getMessage(); } } printer()->throw(new \Exception('Ooops...')); ``` Coroutine supports stopping and continuing execution while maintaining the current state. Coroutine remembers its call stack, data inside, and can use them in the future.
### Generators and Promises! ```[php][] class Generator { public function send($data); public function throw(\Throwable $error); } class Promise { public function resolve($data); public function reject(\Throwable $error); } ```
### Let's use it! ```[php] [|3|5-8|10-13] function recoil(\Generator $generator) { $promise = $generator->current(); $promise->onResolve(function($data) use ($generator) { $generator->send($data); recoil($generator); }; $promise->onReject(function ($error) use ($generator) { $generator->throw($error); recoil($generator); }); } ```

Cooperative multitasking

Database Search Index Cache

Cooperative multitasking IRL

Database Search Index Cache

Cooperative multitasking. What if?

Database Search Index Cache

Cooperative multitasking. In Non-Blocking World

Database Search Index Cache

Handling request

nginx as reverse proxy
  • Advantages:
    • Simple error handling
    • No memory leaks
  • Disadvantages:
    • N+1 limit for workers
    • Context switch overhead
### Async handling ```[php] [|2-3|5|7-12|13] Loop::run(function () { $app = new Application(); $app->bootstrap(); $sockets = [Socket\listen('0.0.0.0:80')]; $server = new Server($sockets, new CallableRequestHandler( function (Request $request) use ($app) { $r = yield $app->dispatch($request); return new Response(Status::OK, [], $response); }) ); yield $server->start(); }); ```
### Problems * Memory leaks * Blocking operations * Library support * Types (yield returns generics?) * No standards for promises

Should I use it in prod? Probably not

Situation is under control.
Calm down, please.
Give me your attention for a moment.
I'll be glad to tell you what happened.

### [RFC::Fibers](https://wiki.php.net/rfc/fibers) feat [AMP v3](https://github.com/amphp/amp/tree/v3) ```[php] [|6-8|10-11|13-17] use Amp\Delayed; use Amp\Loop; use function Amp\async; use function Amp\await; $callback = function (int $id): int { return await(new Delayed(1000, $id)); }; $result = $callback(1); \var_dump($result); $result = await([ async($callback, 2), async($callback, 3), ]); \var_dump($result); ```

Bright nearest future

Where is the profit?

benchmark async

But I want something to play right now! Go for it

roadrunner
gopher

But why?

gopher
### It is simple * No classes * No inheritance * No constructors * No annotations * No generics * No exceptions
### Meanwhile * Async by design * Goroutines * Garbage collection * Strict typing * Active community * Single binary docker container * DI and ORM - bad practice * Cross-platform compilation

Success story #0

Badoo - Consume FacebookApi x20 faster

badoo

Success story #1

Mail.Ru - Billion pushes with Go

badoo

Success story #2

tutu.ru - Rebooking tickets

tutu

Success story #3

go in apps

Story #4

jarvis-notify

Image Docker image Size, Mb
Alpine + curl + jq jb/curl 10.1
raw Go jb-utils/go-notify 5.21
Alpine + Bash + Go jb-utils/notify 10.8

One more thing



web socket
### Websockets in javascript ```[javascript] [] const socket = new WebSocket('ws://localhost:8080'); socket.addEventListener('open', function (event) { socket.send('Hello Server!'); }); socket.addEventListener('message', function (event) { console.log('Message from server ', event.data); }); ```
### Websockets in go ```[go] [] import ( "net/http" "some/websocket" ) http.HandleFunc("/v1/ws", func(w http.ResponseWriter, r *http.Request) { conn, _ := websocket.Upgrade(r, w) ch := NewChannel(conn) //... }) ```

Websockets in php

Library Stars
Ratchet PSR-4 5.3k
websocket-php 0.5k
pusher-http-php 3rd party 1.1k
phpdaemon Is it still alive? 1.5k
Centrifugo Language agnostic 4.9k