Slide 1

Slide 1 text

Saturday, October 6, 12

Slide 2

Slide 2 text

@igorwesome Saturday, October 6, 12

Slide 3

Slide 3 text

Saturday, October 6, 12

Slide 4

Slide 4 text

Saturday, October 6, 12

Slide 5

Slide 5 text

Saturday, October 6, 12

Slide 6

Slide 6 text

var http = require('http'); var server = new http.Server(); server.on('request', function (req, res) { res.writeHead(200, {'Content-Type': 'text/plain'}); res.end('Hello World\n'); }); server.listen(1337, '127.0.0.1'); Saturday, October 6, 12

Slide 7

Slide 7 text

Saturday, October 6, 12

Slide 8

Slide 8 text

Saturday, October 6, 12

Slide 9

Slide 9 text

$server = stream_socket_server('tcp://127.0.0.1:1337'); while ($conn = stream_socket_accept($server, -1)) { fwrite($conn, "HTTP/1.1 200 OK\r\n"); fwrite($conn, "Content-Length: 3\r\n\r\n"); fwrite($conn, "Hi\n"); fclose($conn); } Saturday, October 6, 12

Slide 10

Slide 10 text

$s=stream_socket_server('tcp://[::1]:81'); while($c=stream_socket_accept($s,-1)) fwrite($c,"HTTP/1.1 200 OK\r\nContent-Length: 2\r\n\r\nHi"); Saturday, October 6, 12

Slide 11

Slide 11 text

Non-blocking I/O Saturday, October 6, 12

Slide 12

Slide 12 text

C10K Saturday, October 6, 12

Slide 13

Slide 13 text

Calculations are fast, I/O is slow. Saturday, October 6, 12

Slide 14

Slide 14 text

Latency Comparison Numbers -------------------------- 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 Send 1K bytes over 1 Gbps network 10,000 ns 0.01 ms Read 4K randomly from SSD* 150,000 ns 0.15 ms Read 1 MB sequentially from memory 250,000 ns 0.25 ms 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 Saturday, October 6, 12

Slide 15

Slide 15 text

Latency Comparison Numbers -------------------------- 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 Send 1K bytes over 1 Gbps network 10,000 ns 0.01 ms Read 4K randomly from SSD* 150,000 ns 0.15 ms Read 1 MB sequentially from memory 250,000 ns 0.25 ms 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 Saturday, October 6, 12

Slide 16

Slide 16 text

Saturday, October 6, 12

Slide 17

Slide 17 text

stream_select Saturday, October 6, 12

Slide 18

Slide 18 text

$readable = $read ?: null; $writable = $write ?: null; $except = null; if (stream_select($readable, $writable, $except, 1)) { if ($readable) { foreach ($readable as $stream) { ... } } if ($writable) { foreach ($writable as $stream) { ... } } } Saturday, October 6, 12

Slide 19

Slide 19 text

$readable = $read ?: null; $writable = $write ?: null; $except = null; if (stream_select($readable, $writable, $except, 1)) { if ($readable) { foreach ($readable as $stream) { ... } } if ($writable) { foreach ($writable as $stream) { ... } } } Event Loop Saturday, October 6, 12

Slide 20

Slide 20 text

Saturday, October 6, 12

Slide 21

Slide 21 text

$server = stream_socket_server('tcp://127.0.0.1:1337'); $read = [$server]; $write = []; ... // deep in the event loop foreach ($readable as $stream) { if ($server === $stream) { $conn = stream_socket_accept($server, 0); $read[] = $conn; } else { $data = fread($stream, 1024); echo $data; } } Saturday, October 6, 12

Slide 22

Slide 22 text

Saturday, October 6, 12

Slide 23

Slide 23 text

Saturday, October 6, 12

Slide 24

Slide 24 text

Event-driven, non-blocking I/O with PHP. Saturday, October 6, 12

Slide 25

Slide 25 text

$loop = React\EventLoop\Factory::create(); $socket = new React\Socket\Server($loop); $http = new React\Http\Server($socket, $loop); $http->on('request', function ($req, $rep) { $rep->writeHead(); $rep->end("Hello World!\n"); }); $socket->listen(8080); $loop->run(); Saturday, October 6, 12

Slide 26

Slide 26 text

$loop = React\EventLoop\Factory::create(); $socket = new React\Socket\Server($loop); $socket->on('connection', function ($conn) { $conn->pipe($conn); }); $socket->listen(4000); $loop->run(); Saturday, October 6, 12

Slide 27

Slide 27 text

Saturday, October 6, 12

Slide 28

Slide 28 text

# composer.json { "require": { "react/http": "0.2.*" } } Saturday, October 6, 12

Slide 29

Slide 29 text

$ composer install Saturday, October 6, 12

Slide 30

Slide 30 text

Saturday, October 6, 12

Slide 31

Slide 31 text

Philosophy Saturday, October 6, 12

Slide 32

Slide 32 text

Architecture Saturday, October 6, 12

Slide 33

Slide 33 text

Événement EventEmitter for PHP Saturday, October 6, 12

Slide 34

Slide 34 text

$emitter = new Evenement\EventEmitter(); $emitter->on('data', function ($data) { echo $data; }); $emitter->emit('data', [$data]); Saturday, October 6, 12

Slide 35

Slide 35 text

EventLoop Stream Socket Http Saturday, October 6, 12

Slide 36

Slide 36 text

EventLoop $loop = React\EventLoop\Factory::create(); $server = stream_socket_server('tcp://127.0.0.1:8080'); stream_set_blocking($server, 0); $loop->addReadStream($server, function ($server) use ($loop) { $conn = stream_socket_accept($server); ... }); Saturday, October 6, 12

Slide 37

Slide 37 text

EventLoop $loop->addPeriodicTimer(5, function () { $memory = memory_get_usage() / 1024; $formatted = number_format($memory, 3).'K'; echo "Current memory usage: {$formatted}\n"; }); Saturday, October 6, 12

Slide 38

Slide 38 text

EventLoop $loop->run(); Saturday, October 6, 12

Slide 39

Slide 39 text

EventLoop backends stream_select libevent upcoming libev libuv Saturday, October 6, 12

Slide 40

Slide 40 text

ReadableStream isReadable() pause() resume() close() Events data, end, error, close Stream Saturday, October 6, 12

Slide 41

Slide 41 text

ReadableStream isReadable() pause() resume() close() Events data, end, error, close Stream Saturday, October 6, 12

Slide 42

Slide 42 text

WritableStream isWritable() write($data) end($data) close() Events drain, error, close, pipe Stream Saturday, October 6, 12

Slide 43

Slide 43 text

WritableStream isWritable() write($data) end($data) close() Events drain, error, close, pipe Stream Saturday, October 6, 12

Slide 44

Slide 44 text

Stream $source = new React\Stream\Stream(fopen('omg.txt', 'r'), $loop); $dest = new React\Stream\Stream(fopen('wtf.txt', 'w'), $loop); $source->pipe($dest); Saturday, October 6, 12

Slide 45

Slide 45 text

Stream $a->pipe($b)->pipe($c); a | b | c Saturday, October 6, 12

Slide 46

Slide 46 text

Socket $socket = new React\Socket\Server($loop); $socket->on('connection', function ($conn) { $conn->write("Hello there!\n"); $conn->write("Welcome to this amazing server!\n"); $conn->write("Here's a tip: don't say anything.\n"); $conn->on('data', function ($data) use ($conn) { $conn->close(); }); }); $socket->listen(1337); Saturday, October 6, 12

Slide 47

Slide 47 text

Http $socket = new React\Socket\Server($loop); $http = new React\Http\Server($socket); $http->on('request', function ($request, $response) { $response->writeHead(200, ['Content-Type' => 'text/plain']); $response->end("Hello World!\n"); }); $socket->listen(1337); Saturday, October 6, 12

Slide 48

Slide 48 text

Http $http = new React\Http\Server($socket); $http->on('request', function ($request, $response) { $response->writeHead(200, ['Content-Type' => 'text/plain']); $request->pipe($response); }); Saturday, October 6, 12

Slide 49

Slide 49 text

$waiting = null; $socket->on('connection', function ($conn) use (&$waiting) { if (null === $waiting || !$waiting->isReadable()) { $waiting = $conn; $conn->write("Please wait until a partner connects.\n"); return; } $message = "You are now talking to %s.\n"; $conn->write(sprintf($message, getConnectionId($waiting))); $waiting->write(sprintf($message, getConnectionId($conn))); $conn->pipe($waiting)->pipe($conn); $waiting = null; }); Saturday, October 6, 12

Slide 50

Slide 50 text

Saturday, October 6, 12

Slide 51

Slide 51 text

Saturday, October 6, 12

Slide 52

Slide 52 text

React in the industry: It’s like, so amazing, man. Saturday, October 6, 12

Slide 53

Slide 53 text

Saturday, October 6, 12

Slide 54

Slide 54 text

Saturday, October 6, 12

Slide 55

Slide 55 text

Saturday, October 6, 12

Slide 56

Slide 56 text

Saturday, October 6, 12

Slide 57

Slide 57 text

Saturday, October 6, 12

Slide 58

Slide 58 text

Saturday, October 6, 12

Slide 59

Slide 59 text

React in the industry: It’s like, so amazing, man. Saturday, October 6, 12

Slide 60

Slide 60 text

React in the industry: Saturday, October 6, 12

Slide 61

Slide 61 text

React/ZMQ Saturday, October 6, 12

Slide 62

Slide 62 text

$context = new React\ZMQ\Context($loop); $push = $context->getSocket(ZMQ::SOCKET_PUSH); $push->connect('tcp://127.0.0.1:5555'); $push->send('hello'); Saturday, October 6, 12

Slide 63

Slide 63 text

$context = new React\ZMQ\Context($loop); $pull = $context->getSocket(ZMQ::SOCKET_PULL); $pull->bind('tcp://127.0.0.1:5555'); $pull->on('message', function ($msg) { echo "Received: $msg\n"; }); Saturday, October 6, 12

Slide 64

Slide 64 text

React/STOMP Saturday, October 6, 12

Slide 65

Slide 65 text

React/Whois Saturday, October 6, 12

Slide 66

Slide 66 text

Wisdom Saturday, October 6, 12

Slide 67

Slide 67 text

Saturday, October 6, 12

Slide 68

Slide 68 text

$foo->get(function ($bar) { $bar->get(function ($baz) { $baz->get(function ($bazinga) { $bazinga->get(function () { throw new FuckItException(); }); }); }); }); Saturday, October 6, 12

Slide 69

Slide 69 text

React/Async Saturday, October 6, 12

Slide 70

Slide 70 text

use React\Async\Util as Async; Async::waterfall([ function ($callback) use ($foo) { $foo->get($callback); }, function ($bar, $callback) { $bar->get($callback); }, function ($baz, $callback) { $baz->get($callback); }, function ($bazinga, $callback) { $bazinga->get($callback); }, function ($callback) { throw new FuckItException(); } ]); Saturday, October 6, 12

Slide 71

Slide 71 text

React/Curry Saturday, October 6, 12

Slide 72

Slide 72 text

use React\Curry\Util as Curry; $add = function ($a, $b) { return $a + $b; }; $addOne = Curry::bind($add, 1); echo sprintf("%s\n", $addOne(5)); // outputs 6 Saturday, October 6, 12

Slide 73

Slide 73 text

public function query($domain, $callback) { Async::waterfall( [ Curry::bind([$this, 'resolveWhoisServer'], $domain), Curry::bind([$this, 'queryWhoisServer'], $domain), ], $callback ); } public function resolveWhoisServer($domain, $callback) public function queryWhoisServer($domain, $ip, $callback) Saturday, October 6, 12

Slide 74

Slide 74 text

React in the industry: Saturday, October 6, 12

Slide 75

Slide 75 text

Ratchet Saturday, October 6, 12

Slide 76

Slide 76 text

Predis/Async Saturday, October 6, 12

Slide 77

Slide 77 text

$client->connect(function ($client) { $client->monitor(function ($event) { echo implode(' ', [ "[{$event->timestamp}]", $event->command, $event->arguments, ]); echo "\n"; }); }); Saturday, October 6, 12

Slide 78

Slide 78 text

DNode-PHP Saturday, October 6, 12

Slide 79

Slide 79 text

Huston we have a blocking call Saturday, October 6, 12

Slide 80

Slide 80 text

DNS Saturday, October 6, 12

Slide 81

Slide 81 text

Http Server Worker Client Worker Worker Client Client HTTP Saturday, October 6, 12

Slide 82

Slide 82 text

Saturday, October 6, 12

Slide 83

Slide 83 text

Saturday, October 6, 12

Slide 84

Slide 84 text

Questions? • joind.in/6942 • nodephp.org • @reactphp • @igorwesome Saturday, October 6, 12

Slide 85

Slide 85 text

Saturday, October 6, 12