ARKADIUSZ KONDAS
Data Scientist
@ Buddy
Zend Certified Engineer
@ ArkadiuszKondas
arkadiuszkondas.com
Zend Certified Architect
$urls = ['amazon.com', 'ebay.com', 'allegro.pl'];
foreach ($urls as $url) {
    $content = file_get_contents(
        sprintf('http://%s', $url)
    );
}
amazon.com:    1.3739
ebay.com:      1.4950
allegro.pl:    0.4184
Total time:    3.2877Latency numbers every programmer should know
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 msLets multiply all these durations by a billion
L1 cache reference                  0.5 s         One heart beat (0.5 s)
Branch mispredict                   5 s           Yawn
L2 cache reference                  7 s           Long yawn
Mutex lock/unlock                   25 s          Making a coffeeMinute
Main memory reference               100 s         Brushing your teeth
Compress 1K bytes with Zippy        50 min        One episode of a TV show (including ad breaks)Hour
Send 2K bytes over 1 Gbps network   5.5 hr        From lunch to end of work dayDay
SSD random read                     1.7 days      A normal weekend
Read 1 MB sequentially from memory  2.9 days      A long weekend
Round trip within same datacenter   5.8 days      A medium vacation
Read 1 MB sequentially from SSD    11.6 days      Waiting for almost 2 weeks for a deliveryWeek
Disk seek                           16.5 weeks    A semester in university
Read 1 MB sequentially from disk    7.8 months    Almost producing a new human being
The above 2 together                1 yearYear
Send packet CA->Netherlands->CA     4.8 years     Average time it takes to complete a bachelor's degreeDecade
You can buy a 1000MHz machine with 2 gigabytes of RAM and an 1000Mbit/sec Ethernet card for $1200 or so. Let's see - 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. (Dan Kegel)
10–12 million connections (MigratoryData, 12 cores, using Java on Linux
https://mrotaru.wordpress.com/2013/10/10/scaling-to-12-million-concurrent-connections-how-migratorydata-did-it/
Threads
Apache
Multiplexing
kevent/select/pool
https://help.dreamhost.com/hc/en-us/articles/215945987-Web-server-performance-comparison
var http = require('http');
var urls = ['amazon.com', 'ebay.com', 'allegro.pl'];
for (let i in urls) {
    http.get('http://' + urls[i], function(response){
        var str = '';
        response.on('data', function(chunk) {
            str += chunk;
        });
        response.on('end', function(){});
    });
}
allegro.pl:   0.3901
amazon.com:   0.4755
ebay.com:     0.6653
Total time:   0.6756
amazon.com:    1.3739
ebay.com:      1.4950
allegro.pl:    0.4184
Total time:    3.2877SELECT(2)                                    Linux Programmer's Manual                          
NAME
       select, pselect, FD_CLR, FD_ISSET, FD_SET, FD_ZERO - synchronous I/O multiplexing
SYNOPSIS
       /* According to POSIX.1-2001, POSIX.1-2008 */
       #include <sys/select.h>
       int select(int nfds, fd_set *readfds, fd_set *writefds,
                  fd_set *exceptfds, struct timeval *timeout);
       int pselect(int nfds, fd_set *readfds, fd_set *writefds,
                   fd_set *exceptfds, const struct timespec *timeout,
                   const sigset_t *sigmask);
DESCRIPTION
       select()  and  pselect()  allow a program to monitor multiple file descriptors, 
       waiting until one or more of the file descriptors become "ready" for some class
       of I/O operation (e.g., input possible).  A file descriptor  is  considered  
       ready if it is possible to perform a corresponding I/O operation (e.g., read(2) 
       without blocking, or a sufficiently small write(2)).
<?php
$readable = [stream_socket_client(), stream_socket_client()];
$writable = $writeStreams;
$except = [];
while(true) {
    if (stream_select($readable, $writable, $except, 1)) {
        foreach ($readable as $stream) {
    
        }
        foreach ($writable as $stream) {
    
        }
    }
}EventEmmiter
EventLoop
Stream
Socket
ChildProcess
DNS
Http
HttpClient
Stomp
ØMQ
Whois
Redis
WebSockets
AR.drone
Promise
Filesystem
$emitter = new Evenement\EventEmitter();
$emitter->on('data', function ($data) {
    echo $data;
});
$emitter->emit('data', [$data]);$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);
    $loop->addWriteStream($conn, function ($conn)  {
    });
});
$loop->addPeriodicTimer(5, function () {
    $memory = memory_get_usage() / 1024;
    $formatted = number_format($memory, 3).'K';
    echo "Current memory usage: {$formatted}\n";
});
$loop->run();Asynchronous != Parallel
interface ReadableStreamInterface
{
    public function isReadable();
    public function pause();
    public function resume();
    public function close();
    public function pipe(WritableStreamInterface $dest, array $options = array());
}
Events: data, error, end, close
interface WritableStreamInterface
{
    public function isWritable();
    public function write($data);
    public function end($data = null);
    public function close();
}
Events: drain, error, close, pipeuse React\EventLoop\Factory;
use React\Stream\ReadableResourceStream;
use React\Stream\WritableResourceStream;
$loop = Factory::create();
$source = new ReadableResourceStream(
    fopen('omg.txt', 'r'), $loop
);
$dest = new WritableResourceStream(
    fopen('wtf.txt', 'w'), $loop
);
$source->pipe($dest);
$loop->run();$loop = React\EventLoop\Factory::create();
$socket = new React\Socket\Server(8080, $loop);
$socket->on('connection', function (ConnectionInterface $conn) {
    $conn->write("Hello " . $conn->getRemoteAddress() . "!\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();
    });
});
$loop->run();$urls = ['...', '...'];
$promises = [];
foreach($urls as $url) {
    $deferred = new Promise\Deferred();
    $request = $client->request('GET', $url);
    $request->on('response', 
    function ($response) use ($deferred, $url) {
        $response->on('end', function ($data) use ($deferred, $url) {
            $deferred->resolve($url);
        });            
    });
    $request->end();
    $promises[] = $deferred->promise();
}
Promise\race($promises)->then(function($value) {
	echo $value . " wins the race!" . PHP_EOL;
});
$loop = \React\EventLoop\Factory::create();
$factory = new \React\Dns\Resolver\Factory();
$dns = $factory->create('8.8.8.8', $loop);
$dns->resolve($argv[1])
    ->then(
        function ($ip) { echo "Host: $ip\n"; },
        function ($error) { echo "Error: {$error->getMessage()}\n"; }
    );
$loop->run();php bin/promise.php 4developers.pl
Host: 87.98.239.5
php bin/promise.php aaa           
Error: DNS Request did not return valid answer.
$loop = React\EventLoop\Factory::create();
$process = new React\ChildProcess\Process('echo foo');
$process->start($loop);
$process->stdout->on('data', function ($chunk) {
    echo $chunk;
});
$process->on('exit', function($exitCode, $termSignal) {
    echo 'Process exited with code ' . $exitCode . PHP_EOL;
});
$loop->run();$connection->on('data', function ($data) use ($server, $connection) {
  $data = trim(preg_replace('/[^\w\d \.\,\-\!\?]/u', '', $data));
  if ($data === '') {
  	return;
  }
  $data = parse_url($connection->getRemoteAddress(), PHP_URL_HOST) 
      . ': ' . $data . PHP_EOL;
  foreach ($server->getConnections() as $client) {
  	if($connection !== $client) {
  		$client->write($data);
  	}
  }
});Text
VS
https://philsturgeon.uk/php/2013/11/12/benchmarking-codswallop-nodejs-v-php/
bit.ly/phpsmasher
http://socketo.me/
https://github.com/nrk/predis-async
https://github.com/jolicode/php-ar-drone
$drone->on('landed', function() {
    // do something
});
$drone
    ->after(3, function () use ($drone) {
        $drone->up(0.6);
    })
    ->after(4, function () use ($drone) {
        $drone->stop();
    })
    ->after(1, function () use ($drone) {
        $drone->left(0.3);
    })
$drone->start();opcache
please enable opcache
https://github.com/php-pm/php-pm
Asynchronous Multitasking PHP: Hypertext Preprocessor
https://github.com/amphp
function slowAddition($x, $y) {
    sleep(1);
    return $x + $y;
}
$dispatcher = new Amp\Thread\Dispatcher;
$a = $dispatcher->call('slowAddition', 1, 5);
$b = $dispatcher->call('slowAddition', 10, 10);
$c = $dispatcher->call('slowAddition', 11, 31);
$comboPromise = Amp\all([$a, $b, $c]);
list($a, $b, $c) = $comboPromise->wait();https://github.com/swoole/swoole-src
Swoole is an event-driven asynchronous & concurrent networking communication framework with high performance written only in C for PHP.
http://nikic.github.io/2012/12/22/Cooperative-multitasking-using-coroutines-in-PHP.html
Cooperative multitasking using coroutines (in PHP!)
by Nikita Popov
@ ArkadiuszKondas
https://github.com/akondas