React.PHP

 React.PHP

A0f86e1e045f197a5852ea5a2665df8c?s=128

Karel Čížek

June 29, 2013
Tweet

Transcript

  1. React.PHP

  2. K. k47.cz @kaja47 Karel Čížex funkcionalne.cz

  3. http://reactphp.org/

  4. There's nothing we cannot steal. Let's steal node.js

  5. node.js? PHP? wat?

  6. event driven, non-blocking, reactive, async IO

  7. buzzword, buzzword, buzzword, buzzword

  8. CPU je rychlé, IO je pomalé

  9. L1 cache reference ......................... 0.5 ns Branch mispredict ............................ 5

    ns L2 cache reference ........................... 7 ns Mutex lock/unlock ........................... 25 ns Main memory reference ...................... 100 ns Compress 1K bytes with Zippy ............. 3,000 ns = 3 µs Send 2K bytes over 1 Gbps network ....... 20,000 ns = 20 µs SSD random read ........................ 150,000 ns = 150 µs Read 1 MB sequentially from memory ..... 250,000 ns = 250 µs Round trip within same datacenter ...... 500,000 ns = 0.5 ms Read 1 MB sequentially from SSD ...... 1,000,000 ns = 1 ms Disk seek ........................... 10,000,000 ns = 10 ms Read 1 MB sequentially from disk .... 20,000,000 ns = 20 ms Send packet CA->Netherlands->CA .... 150,000,000 ns = 150 ms
  10. c10k

  11. Na IO musíme čekat

  12. Čekání blokuje vlákno

  13. Potřebujeme hodně vláken

  14. Vlákna zabírají paměť

  15. 10k vláken zabere hodně paměti

  16. c10M

  17. async non-blocking = 1 vlákno

  18. epoll

  19. stream_select(&$readable, &$writable, &$exc, $timeout)

  20. while (true) { ... stream_select($readable, $writable, $err, $timeout) ... }

  21. >-(IO)->-(IO)---------------------->-(IO)---->-(CPU)->-(CPU)->-(CPU)-> >-(IO)->-(CPU)-> >-(IO)---------------------->-(CPU)-> >-(IO)----> -(CPU)->

  22. Reaktivní aplikace WebSockets Async end-to-end Par { MySQL, Redis, HTTP,

    FS } Cron
  23. React.PHP (gory details)

  24. Http Socket Stream EventLoop

  25. HttpClient | DNS | WebSocket | ZeroMQ Socket Stream EventLoop

  26. $loop = React\EventLoop\Factory::create(); $socket = new React\Socket\Server($loop); $http = new

    React\Http\Server($socket, $loop); $http->on('request', function ($request, $response) { $response->writeHead(200, ['Content-Type' => 'text/plain']); $response->end("Hello World\n"); }); $socket->listen(1337); $loop->run();
  27. Server napsaný v PHP, který běží v PHP procesu

  28. Jednovláknový

  29. $loop->addPeriodicTimer(60*60*24*7, function ($timer) { hideBodies(ALL_OF_THEM); });

  30. http://autotweeter.k47.cz

  31. In-memory

  32. http://onlyoc.jdem.cz

  33. worker --> DB <-- Apache worker ------------> React

  34. [your ad here]

  35. callbax: call(function ($a) { call(function ($b) use ($a) { call(function

    ($c) use ($a, $b) { throw new Exception('Where is your god now?'); }); }); });
  36. callbax: $http->on('connect', function ($req, $resp) { $req->on('data', function ($postData) {

    parse_str($postData, $post); $users->getById($post['id'], function ($err, $user) { renderUser($user, $resp); }); } });
  37. callback == continuation

  38. Callback hell Composition Coordination

  39. Promise!

  40. Deferred / Resolved / Rejected

  41. Promise = hodnota (FP) Callback = proces

  42. Promise[IO]

  43. ->then($ok, $err)

  44. Callback hell Hodnota vs. proces

  45. Kompozice $p->then($f)->then($g) (chyby) throw

  46. // map (Functor) fetchPost($id)->then(function ($post) { return toJson($post, PRETTY); });

    // flatMap (Monad) fetchPost($id)->then(function ($post) { return fetchPost($post->parentId); }); // robot unicorn attack loadFromCache()->then(null, 'loadFromDatabase')
  47. $deferred = new React\Promise\Deferred(); $promise = $deferred->promise(); $resolver = $deferred->resolver();

    $resolver->resolve('I\'m Boxxy you see') $resolver->reject(new \Exception('U dun goofed'));
  48. React: Promise Resolver Scala: Future Promise C#: Task TaskCompletionSource

  49. Koordinace

  50. When::any($ps) When::some($ps, $n) When::all($ps) When::map($ps, $f) When::reduce($ps, $f) When::lazy($f)

  51. $data = []; $callback = function($err, $val) use (&$data) {

    $data[] = $val; // pořadí? if (count($data) == 3) { realCallback($err, $data); } // chyby? chybějí! } fetch('ak', $callback); fetch('ruby', $callback); fetch('peo', $callback);
  52. When::all(getUsers(), getCategories(), getLastPosts()); When::any(server(1), server(2), server(3)); When::all( When::map(getLastPost(), 'getComments'), getCategories(),

    getTweetsFromCache() ->then(null, 'fetchTweets') ->then('tranform', function () { return []; }) );
  53. function timeout($time, $promise, $loop) { $defer = new React\Promise\Deferred; $r

    = $defer->resolver(); $sig = $loop->addTimer($time, function() use($r) { $r->reject('timeout'); }); $promise->then( function ($x) use($r, $sig, $loop) { $loop->cancelTimer($sig); $r->resolve($x); }, function ($e) use($r) { $r->reject($e); } ); return $defer->promise(); }
  54. To je všechno pěkné, ale...

  55. // fetch all followers $profile = fetchProfile('kaja47'); $ids = [];

    $cursor = '-1'; do { $fs = fetchFollowers($profile->id, $cursor); $ids = array_merge($ids, $fs->ids); $cursor = $fs->next_cursor_str; } while ($cursor != "0") return [$profile, $ids];
  56. // async clusterfuck fetchProfile($userName)->then(function ($profile) { $fetch = function($userId, $cursor)

    use (&$fetch) { return fetchFollowers($userId, $cursor)->then(function ($fs) use ($userId) { $cursor = $fs->next_cursor_str; if ($cursor == "0") return When::resolve($fs->ids); else return $fetch($userId, $cursor)->then(function($ids) use($fs) { return array_merge($fs->ids, ids); }); }); }; $fetch($profile->id, '-1')->then(function($ids) use($ids) { return [$profile, $ids]; }) });
  57. CPS

  58. C# : async/await Iced Coffeescript: await/defer Scala: for/shift/reset/flow/makra

  59. PHP 5.5 & yield

  60. // async flow(function() { $profile = (yield fetchProfile('kaja47')); $ids =

    []; $cursor = '-1'; do { $fs = (yield fetchFollowers($profile->id, $cursor)); $ids = array_merge($ids, $fs->ids); $cursor = $fs->next_cursor_str; } while ($cursor != "0") yield [$profile, $ids]; });
  61. function flow(Closure $f) { $gen = $f(); $fst = true;

    $recur = function($pureValue) use($gen, &$recur, &$fst) { $x = $fst ? $gen->current() : $gen->send($pureValue); $fst = false; if (!$gen->valid()) return $pureValue; if ($x instanceof Promise) return $x->then($recur); else return $recur($x); }; return $recur(null); }
  62. [your ad here]

  63. Co dál?

  64. Reactive Nette

  65. Async errything

  66. FS HttpClient WebSocket Redis ZeroMQ STOMP (RabbitMQ) SOCKS IRC Dnode

    MySQL (non-reactive)
  67. Výkon PHP < V8

  68. Native async extension VM (JIT/tracing) GC Datové struktury

  69. Rx Iteratees

  70. popularita efektivita ⇒

  71. This is the end Beautiful friend This is the end

    My only friend, the end Of our elaborate plans, the end Of everything that stands, the end No safety or surprise, the end I'll never look into your eyes...again Can you picture what will be So limitless and free Desperately in need...of some...stranger's hand In a...desperate land Lost in a Roman...wilderness of pain And all the children are insane All the children are insane Waiting for the summer rain, yeah
  72. http://reactphp.org/ https://github.com/reactphp https://gist.github.com/hellerbarde/2843375 http://conference.phpnw.org.uk/phpnw12/schedule/igor-wiedler/#video http://blog.jcoglan.com/2013/03/30/callbacks-are-imperative-promises-are-fu nctional-nodes-biggest-missed-opportunity/ http://blog.jcoglan.com/2013/04/01/callbacks-promises-and-simplicity/ https://gist.github.com/domenic/3889970 http://blog.parse.com/2013/01/29/whats-so-great-about-javascript-promises/ http://brianmckenna.org/blog/category_theory_promisesaplus

    http://www.dartlang.org/articles/using-future-based-apis/ http://marakana.com/s/post/1453/redemption_from_callback_hell_michael_ja ckson_domenic_denicola_video https://github.com/kaja47/flow https://github.com/kaja47/async-mysql https://gist.github.com/kaja47/4407844
  73. will-work-for-food@k47.cz