react php: the nodejs challenger

35
REACT PHP The NodeJS Challenger LUKE KYSOW Software Engineer @Hootsuite Find me on Twitter @lkysow

Upload: vanphp

Post on 23-Jun-2015

3.109 views

Category:

Technology


0 download

DESCRIPTION

Event looped, asynchronous programming is possible with PHP! Streams, promises, async IO, web sockets -- you can do it all, with React PHP. Presented by Luke Kysow.

TRANSCRIPT

Page 1: React PHP: the NodeJS challenger

REACT PHPThe NodeJS Challenger

LUKE KYSOWSoftware Engineer @Hootsuite

Find me on Twitter @lkysow

Page 2: React PHP: the NodeJS challenger

What is ReactPHP?

Written by Igor Wiedler • @igorwhiletrue

Page 3: React PHP: the NodeJS challenger

$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(8000);$loop->run();

Page 4: React PHP: the NodeJS challenger

What Does PHPSuck At?

Page 5: React PHP: the NodeJS challenger

C10K Problem

Page 6: React PHP: the NodeJS challenger

Websockets

Page 7: React PHP: the NodeJS challenger

Making lots of concurrentrequests (ex. Web Scraping)

Page 8: React PHP: the NodeJS challenger

Speed

Page 9: React PHP: the NodeJS challenger

Why does PHPsuck at solvingthese problems?

Page 10: React PHP: the NodeJS challenger

Why is NodeJSgood at solvingthese problems?

Page 11: React PHP: the NodeJS challenger

A typical web request<?php

$request = $this->getRequest();$param = $request->getParameter('param');

// these calls block$apiResponse = $api->getSomething($param);$dbResponse = $database->doSomething($param);

return new Response($apiResponse, $dbResponse

Page 12: React PHP: the NodeJS challenger

Latency Numbers EveryProgrammer Should Know

L1 cache reference 0.5 nsL2 cache reference 7 nsMain memory reference 100 nsSend 1K bytes over 1 Gbpsnetwork

10,000 ns

Read 1 MB sequentiallyfrom memory

250,000 ns

Round trip within samedatacenter

500,000 ns

Page 13: React PHP: the NodeJS challenger

A typical web request<?php

$request = $this->getRequest(); // 1ns$param = $request->getParameter('param'); // 1ns

// 100,000,000 ns$apiResponse = $api->getSomething($param);// 500,000 ns$dbResponse = $database->doSomething($param);

// 1nsreturn new Response($apiResponse, $dbResponse

Page 14: React PHP: the NodeJS challenger

Solution:

(╯°□°)╯︵ ┻━┻Implement Non-Blocking I/O

and Event Loops in PHP!

Page 15: React PHP: the NodeJS challenger

Aside: Streams

$filePointer = fopen("http://google.com", "rb"

echo stream_get_contents($filePointer, 25);// "<!doctype html><html item"

echo stream_get_contents($filePointer, 25);// "scope="" itemtype="http:/"

Page 16: React PHP: the NodeJS challenger

Aside: Streams

$filePointer = fopen("file:///tmp/test", "w"

fwrite($filePointer, "Actual React code coming soon");

Page 17: React PHP: the NodeJS challenger

Convert this...<?php

$request = $this->getRequest();$param = $request->getParameter('param');

// these calls block$apiResponse = $api->getSomething($param);$dbResponse = $database->doSomething($param);

return new Response($apiResponse, $dbResponse

Page 18: React PHP: the NodeJS challenger

// get requests as streams$apiStream = $api->getStream($param);$dbStream = $database->getStream($param);

// still blockslist($apiResp, $dbResp) = $this->retrieveData($apiStream, $dbStream);

return new Response($apiResp, $dbResp);

Page 19: React PHP: the NodeJS challenger

$apiStream = $api->getStream($param); $dbStream = $database->getStream($param);

// return asynchronously $this->retrieveStreams($apiStream, $dbStream ->on('streamsReady',

function($apiResp, $dbResp) { return new Response($apiResp, $dbResp } );

Page 20: React PHP: the NodeJS challenger

stream_select

Page 21: React PHP: the NodeJS challenger

$filePointer = fopen("http://google.com", "rb"$readable = [$filePointer];$write = []; $exc = []; $t = 5;

if (stream_select($readable, $write, $exc, $t if ($readable) { $googleStream = $readable[0]; echo stream_get_contents($googleStream, // echoes <!doctype html><html item }}

Page 22: React PHP: the NodeJS challenger

What do we yield control to?

Page 23: React PHP: the NodeJS challenger

An Event Loop<?php

while (true) { $event = $this->getNextEvent(); $event->process();}

Page 24: React PHP: the NodeJS challenger

while (true) { if (stream_select($read, $write, $exc, 1)) { if ($read) { foreach ($readable as $stream) { // run callback for that stream } } if ($write) { foreach ($writable as $stream) { // run callback for that stream }} }}

Page 25: React PHP: the NodeJS challenger

Non Blocking I/O+ Event Loops== Awesome

Page 26: React PHP: the NodeJS challenger

== React PHP

Page 27: React PHP: the NodeJS challenger

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

$socket->on('connection', function ($conn) { $conn->write("Hello there!\n"); $conn->write("Don't say anything...\n");

$conn->on('data', function ($data) use ($conn) { $conn->close(); });});$socket->listen(1337);$loop->run()

Page 28: React PHP: the NodeJS challenger

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

$http->on('request', function ($request, $response) { echo "I see a client!\n"; $response->writeHead(200, ['Content-Type' => 'text/plain']); $response->end("Hello World!\n");});

$socket->listen(1337);$loop->run();

Page 29: React PHP: the NodeJS challenger

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

$socket->on('connection', function ($conn) { $conn->pipe($conn); });

$socket->listen(1337);$loop->run();

Page 30: React PHP: the NodeJS challenger

$waiting = null;$socket->on('connection', function ($conn) use (&$waiting) { if (null === $waiting) { $waiting = $conn; $conn->write("Wait for a partner.\n"); } else { $conn->write("Connected!"); $waiting->write("Connected!");

$conn->pipe($waiting)->pipe($conn); $waiting = null; }});

Page 31: React PHP: the NodeJS challenger

React ProjectsReact In The IndustryWeb Scraping with React

Page 32: React PHP: the NodeJS challenger

High Performance SymfonyTL;DR: You'll get with this approach almost 2.000 requests/s instead of

130 on a large Symfony app.

Even if you have an "opcode cache" you have todeclare classes, instantiate your objects, read your

caches, etc for every single request. As you can surelyimagine this is very time consuming and far awayfrom being a perfect setup for high performance.

http://marcjschmidt.de/blog/2014/02/08/php-high-performance.html

Page 33: React PHP: the NodeJS challenger

Is React PHP aNodeJS

Challenger?

Page 34: React PHP: the NodeJS challenger

NO

Page 35: React PHP: the NodeJS challenger

Fin

Luke Kysow • @lkysow

Please give me your feedback! http://tiny.cc/reactphp