React

Jeremy Mikola
jmikola


MongoDB
### Let’s make a web server

Blocking IO

stream_socket_accept($server, -1)

Why is this a problem?

Blocking IO


IO
CPU
IO
CPU
IO
CPU

Common Latencies

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
Send 1K bytes over 1 Gbps network 10,000 ns
Read 4K randomly from SSD 150,000 ns
Read 1 MB sequentially from memory 250,000 ns
Round trip within same datacenter 500,000 ns
Read 1 MB sequentially from SSD 1,000,000 ns
Disk seek 10,000,000 ns
Read 1 MB sequentially from disk 20,000,000 ns
Round trip from US to Europe 150,000,000 ns

https://gist.github.com/jboner/2841832

Common Latencies

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
Send 1K bytes over 1 Gbps network 10,000 ns
Read 4K randomly from SSD 150,000 ns
Read 1 MB sequentially from memory 250,000 ns
Round trip within same datacenter 500,000 ns
Read 1 MB sequentially from SSD 1,000,000 ns
Disk seek 10,000,000 ns
Read 1 MB sequentially from disk 20,000,000 ns
Round trip from US to Europe 150,000,000 ns

https://gist.github.com/jboner/2841832

C10k Problem

You can buy a 1000MHz machine with 2 gigabytes of RAM and an 1000Mbit/sec Ethernet card for $1200 or so. At 20000 clients, that’s 50KHz, 100Kbytes, and 50Kbits/sec per client.

It shouldn’t take any more horsepower than that to take four kilobytes from the disk and send them to the network once a second for each of twenty thousand clients.

So hardware is no longer the bottleneck.

http://www.kegel.com/c10k.html

Threading


IO
CPU


IO
CPU


IO
CPU

Non-blocking IO


IO
CPU


IO
CPU


IO
CPU
React
Event-driven, non-blocking I/O with PHP.

Reactor Pattern

Resources Demultiplexer Dispatcher Request Handlers

React’s Stack

DNode
AR.Drone
Whois
SOCKS
Redis
WebSockets
Stomp
ØMQ
IRC
DNS
Http
HttpClient
Socket
ChildProcess
Stream
EventLoop

EventEmitter

Event Loop

  • Tracks timers and streams
  • Each loop iteration is a "tick"
  • Ticks execute timers and poll IO
  • Polling timeout can be calculated
  • No timers/streams ends loop

Event Loop

  • Add/remove readable/writable streams
  • Schedule run-once or periodic timers
  • Multiple implementations

Streams

Readable → Writable

CompositeStream

Joins writable and readable streams

ThroughStream

Allows data to be filtered

BufferedSink

Converts writable stream to a promise

Promises

Wouldn’t it be nice if asynchronous
functions could return immediately?

Deferred

  • promise()
  • resolve($value = null)
  • reject($reason = null)
  • progress($update = null)

Computation or unit of work that
may not have completed yet

Promise

Placeholder for the result of a deferred computation

then($onFulfilled, $onRejected, $onProgress)

then() returns a new Promise composing the first

Suggested Reading

“You’re missing the point of promises”
— Domenic Denicola

Now back to the stack…

Avoid Blocking

  • Database queries
  • Disk and file IO
  • CPU-intensive tasks

Helpful Tools

Inter-process communication

Message queues

Break up computations with
$loop->nextTick(callable)


$ composer require "react/react=~0.4"
                    

WebSockets

https://github.com/cboden/Ratchet

GifSockets

https://github.com/videlalvaro/gifsockets
https://github.com/reactphp/gifsocket