Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript --...

85
Generators & Asynchronous Computation AFUP 12/06/2018 Benoit Viguier @b_viguier

Transcript of Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript --...

Page 1: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

Generators &

Asynchronous Computation

AFUP12/06/2018

Benoit Viguier@b_viguier

Page 2: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

Trending Topic🔥🔥🔥

Page 3: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

Joël WurtzPhpTour 2018

Page 4: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

Julien BianchiPhpTour 2016

Page 5: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

Cooperative multitasking using coroutines

(in Php!)

Nikita PopovBlog - 2012

Page 6: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

Asynchrony ≠

Parallel≠

Concurrency

Page 7: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

Concurrency

Page 8: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

Asynchrony

Page 9: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

Parallel

Page 10: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

Asynchronous Concurrency

Exactly what we will talk about!

Page 11: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

Parallel Concurrency

Not today 😉

Page 12: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

Concurrent Only Does it only make sense??

Page 13: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

No Concurrency Ok, but… why would you do that?

Page 14: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

ASYNCHRONOUS PROGRAMMING

EVERYWHERE !

Page 15: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

What you see

Page 16: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

What happens

Page 17: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

How to take/release« ownership » ?

No blocking wait

Page 18: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

EventLoopThe master process

Page 19: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

function run() { while (!$eventLoop->isFinished()) { $task = $eventLoop->popTask(); $task->run(); } }

Page 20: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

EventLoop≠

Http Server

Page 21: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

Events listenerMainly for external events

Page 22: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

ADVISORYPARENTAL

EXPLICIT JAVASCRIPT

Page 23: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

$element.addEventListener ("mousedown" , onMouseDown , false);

function onMouseDown () { // Init and track motion // Code here… document.addEventListener ("mousemove" , onMouseMove , false); }

function onMouseMove (event) { // Move logic here // Code here… document.addEventListener ("mouseup" , onMouseUp , false); }

function onMouseUp () { // Finish motion tracking // Code here… document.removeEventListener ("mousemove" , onMouseMove , false); document.removeEventListener ("mouseup" , onMouseUp , false); }

Page 24: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

PromisesPromises/A+

Page 25: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

PromisesConcept

Page 26: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

# ➡❓ 🚲🎅# ⏸ 🕐# ⏸ 🕑# 🚲⬅ 🎅🚴 . 💃 . ⛹ .

Synchronous

Page 27: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

Asynchronous Promise

# ➡❓🚲 🎅

# 🎫⬅ 🎅

⛹ . 💃 . # 🚲⬅ 🎫🎅🚴 .

Page 28: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

PromisesExample

Page 29: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

// https://reactphp.org/promise/#how-to-use-deferred

getAwesomeResultPromise() ->then( function ($value) { // Deferred resolved, do something with $value }, function ($reason) { // Deferred rejected, do something with $reason }, function ($update) { // Progress notification triggered, do something // with $update } );

Page 30: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

// https://reactphp.org/promise/#mixed-resolution-and-rejection-forwarding

getAwesomeResultPromise() ->then(function ($x) { return $x + 1; }) ->then(function ($x) { throw new \Exception($x + 1); }) ->otherwise(function (\Exception $x) { // Handle the rejection, and don't propagate. // This is like catch without a rethrow return $x->getMessage() + 1; }) ->then(function ($x) { echo 'Mixed '.$x; // 4 });

Page 31: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

// https://reactphp.org/http-client/#example

$loop = React\EventLoop\Factory::create(); $client = new React\HttpClient\Client($loop);

$request = $client->request('GET', 'https://github.com/'); $request->on('response', function ($response) { $response->on('data', function ($chunk) { echo $chunk; }); $response->on('end', function () { echo 'DONE'; }); }); $request->on('error', function (\Exception $e) { echo $e; }); $request->end(); $loop->run();

Page 32: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

PromisesWorkflow

Page 33: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

Promise / Listener

Function #2

Main function

Function #1

Page 34: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

Function #2

Main function1

2

Promise / Listener

Page 35: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

Main1

2

3

4

Promise / Listener

Page 36: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

Main1

2

3

4

5

Promise / Listener

Page 37: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

Not so bad…😕

Page 38: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

What if I told youthat

Generators could be used for

asynchronous computation?

Page 39: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

« Generators in JavaScript -- especially when combined with Promises -- are a very powerful

tool for asynchronous programming as they mitigate -- if not entirely eliminate -- the

problems with callbacks, such as Callback Hell and Inversion of Control.

This pattern is what async functions are built on top of. »

-MDN Web docs

Page 40: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

Generatorsand Coroutines

Page 41: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

// https://secure.php.net/manual/en/language.generators.syntax.php

function gen_one_to_three() { for ($i = 1; $i <= 3; $i++) { yield $i; } }

$generator = gen_one_to_three(); foreach ($generator as $value) { echo "$value\n"; }

Page 42: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

Generators, also known as semicoroutines, are also a generalisation of subroutines, but are

more limited than coroutines.

Coroutines are computer-program components that generalize subroutines for non-preemptive multitasking, by allowing multiple entry points

for suspending and resuming execution at certain locations.

Wikipedia

Page 43: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

GeneratorsAvailable operations

Page 44: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

final class Generator implements Iterator {

function rewind() {}

function valid(): bool {} function current() {}

function key() {}

function next() {}

function send($value) {}

function throw(Throwable $exception) {}

function getReturn() {} }

Page 45: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

Master Coroutine

Child Coroutine

Page 46: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

Master Coroutine

Child Coroutine

$value = $g->current(); $key = $g->key();

yield $key => $value;

Page 47: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

Master Coroutine

Child Coroutine

$g->send($a); $g->next();

$a = yield;

Page 48: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

Master Coroutine

Child Coroutine

$g->throw($e);

try{ yield; } catch(\Exception $e) {}

Page 49: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

Master Coroutine

Child Coroutine

$g->valid(); $r = $g->getReturn();

return $r;

Page 50: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

Example #1Simple workflow

Page 51: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

Main routine

Generator

Page 52: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

Main routine

Generator

1

generator.current

Page 53: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

Main routine

Generator

1

generator.current

yield

2

Page 54: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

Main routine

Generator

1

generator.send

yield

2

3

4

Page 55: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

Generator

1

generator.send

return

2

3

4

5

6

generator.current

Page 56: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

Generator

1

2

3

4

5

6

7

generator.getReturn

Page 57: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

Example #2More generators

Page 58: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

Main routine

Generator #2

Generator #1

Page 59: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

Main routine

Generator #2

1

2

Generator #1

Page 60: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

Main routine

Generator #2

1

2

Generator #1

3

4

Page 61: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

Generator #2

1

2

3

4

5

6

Page 62: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

1

2

3

4

5

6

8

7

Page 63: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

1

2

3

8

5 97 11

4 106

Page 64: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

Generatorsthe weird part…

Page 65: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

// Does NOT work $generator = new \Generator;

// Here the only way to create a// generator function create(): \Generator { yield; }

$generator = create();

Page 66: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

// Only the 'yield' keyword matters function emptyGenerator(): \Generator { return; yield; }

$generator = emptyGenerator();

Page 67: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

function dyingGenerator(): \Generator { die('hard'); yield; }

// The 'die' is not reached, // the function is not executed $generator = dyingGenerator();

// Now it's time to die hard $generator->valid();

Page 68: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

// Do not forget to execute // your anonymous function! $generator = (function (): \Generator { yield; })();

Page 69: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

// Type hinting ✅ function before(): int { return 10; }

// 😭function after(): \Generator { $mixed = yield $mixed; return 10; }

Page 70: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

Event LoopWith generators?

Page 71: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

// https://github.com/amphp/artax/blob/master/examples/1-get-request.php

Loop::run(function () use ($argv) { try { $client = new Amp\Artax\DefaultClient; $promise = $client->request( $argv[1] ?? ‘https://httpbin.org/user-agent' );

$response = yield $promise; print $response->getStatus() . "\n";

$body = yield $response->getBody(); print $body . "\n";

} catch (Amp\Artax\HttpException $error) { echo $error; } });

Page 72: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

Event Loopfrom backstage

Page 73: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

while ($notFinished) { // This is called a tick foreach ($this->tasks as [$g, $gPromise]) {

// Is generator already resolved? // (wait for it…)

// Get Promise to resolve // (wait for it…)

// Is promise finished? // (wait for it…)

} }

Page 74: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

// Is generator already resolved? if (!$g->valid()) { $gPromise->resolve( $g->getReturn() ); $this->remove($g); continue; }

Page 75: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

// Get Promise to resolve $p = $g->current(); if (!$p instanceof PromiseInterface) { throw new \Exception(); }

Page 76: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

// Is promise finished? switch ($p->state()) { case PromiseState::SUCCESS: $g->send($p->getValue()); break; case PromiseState::FAILURE: $g->throw($p->getException()); break; }

Page 77: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

But how are resolved blocking promises?

Page 78: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

// #1 Old fashion listener function tickListener() { $this->tryToFinishTheTask();

if ($this->isFinished) { $this->promise->resolve( $this->result ); } }

Page 79: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

// #2 Top Hype generator 🤘function subEventLoop(): \Generator { while (!$this->isFinished) { yield $this->eventLoop->waitNextTick(); $this->tryToFinishTheTask(); }

return $this->result; }

Page 80: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

Asynchronous Events in Phpstream_selectcurl_multi_execThreadsSystem callInterruptionsextensions …

Page 81: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous
Page 82: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

SOON IN YOUR PROJECT !!

Page 83: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

Use cases

Page 84: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

Fiber RFC ?https://wiki.php.net/rfc/fiber

Page 85: Generators Asynchronous Computation · Parallel ≠ Concurrency ... « Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous

Thanks!@b_viguier