SlideShare a Scribd company logo
The promise of asynchronous PHP
Wim Godden
Cu.be Solutions
@wimgtr
Who am I ?
Wim Godden (@wimgtr)
Where I'm from
Where I'm from
Where I'm from
Where I'm from
Where I'm from
Where I'm from
My town
My town
Belgium – the traffic
Who am I ?
Wim Godden (@wimgtr)
Founder of Cu.be Solutions (http://cu.be)
Open Source developer since 1997
Developer of OpenX, PHPCompatibility, PHPConsistent, ...
Speaker at Open Source conferences
Who are you ?
Developers ?
Ever worked with asynchronous PHP libraries ?
Node.JS ?
Synchronous processing
Asynchronous processing
Blocking I/O
Disk reading/writing
Network reading/writing
Communication with DB (with some exceptions)
Sending mail
...
Non-blocking = good
Work on multiple things at same time
Not entirely sequential anymore
How do you know something is finished ?
→ Events !
Events
Start
Progress update
End (successfully)
Failed
Callback hell
$one->do(function ($two) {
$two->do(function ($three) {
$three->do(function ($stillcounting) {
$stillcounting->get(function() {
throw new IQuitException();
});
});
});
});
State of asynchronous PHP
Several built-in functions
Several libraries (using the built-in functions)
Facebook Hack
Pthreads
PECL extension
Multithreading
Requires zts (thread-safe)
Pthreads
class WebRequest extends Thread {
public $url;
public $response;
public function __construct($url){
$this->url = $url;
}
public function run() {
$this->response = file_get_contents($this->url);
}
}
$request = new WebRequest("http://cu.be");
if ($request->start()) {
/* do some work here */
$a = array_fill(0, 10000000, 'test');
for ($i = 0; $i < count($a); $i++) {}
/* ensure we have data */
$request->join();
var_dump($request->response);
}
pcntl_fork
Clones PHP process
Multiprocessing, not multithreading
No communication between processes
No Apache
popen
child.php
<?php
/* Do some work */
echo 'Output here';
main.php
<?php
// open child process
$child = popen('php child.php', 'r');
/*
* Do some work, while already doing other
* work in the child process.
*/
// get response from child (if any) as soon at it's ready:
$response = stream_get_contents($child);
W
arning
: doesn't behave
sam
e
on
all operating
system
s
!
curl_multi_select
$ch1 = curl_init();
$ch2 = curl_init();
curl_setopt($ch1, CURLOPT_URL, "http://www.google.com/");
curl_setopt($ch2, CURLOPT_URL, "http://www.yahoo.com/");
$mh = curl_multi_init();
curl_multi_add_handle($mh,$ch1);
curl_multi_add_handle($mh,$ch2);
$active = null;
do {
do {
$mrc = curl_multi_exec($mh, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
usleep(1000);
} while (curl_multi_select($mh) === -1);
while ($active && $mrc == CURLM_OK) {
if (curl_multi_select($mh) != -1) {
do {
$mrc = curl_multi_exec($mh, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
}
}
curl_multi_remove_handle($mh, $ch1);
curl_multi_remove_handle($mh, $ch2);
curl_multi_close($mh);
Libevent, libev, libuv
Event handling libraries
PHP extensions
libevent = also used by Memcached
libev = not available on Windows
Using Curl as async system
$c = curl_init();
curl_setopt($c, CURLOPT_URL, 'http://www.long.process.com/calling-
here?action=go&from=4&to=40000');
curl_setopt($c, CURLOPT_FOLLOW_LOCATION, true);
curl_setopt($c, CURLOPT_FRESH_CONNECT, true);
curl_setopt($c, CURLOPT_TIMEOUT_MS, 1);
curl_exec($c);
curl_close($c);
// Code continues after 1ms timeout
ReactPHP
Event-driven non-blocking I/O library
Written in PHP
Provides event-driven interface
Implements event loop
ReactPHP – a simple webserver
$loop = new ReactEventLoopFactory::create();
$socket = new ReactSocketServer($loop);
$http = new ReactHttpServer($socket, $loop);
$http->on('request', function ($request, $response) {
$response->writeHead(200);
$response->end("Hello world!n");
});
$socket->listen(80);
$loop->run();
ReactPHP - structure
Event Loop
Stream
Socket
HTTP
→ stream_select() / libevent / libev
ReactPHP - structure
Event Loop
Stream
Socket
HTTPClient DNSWHOIS HTTPClient
WebsocketSOCKS IRC
ReactPHP – Deferred & Promise
Computation to be performed = Deferred
(ReactPromiseDeferred)
2 possible status :
Resolved
Rejected
ReactPHP – Deferred & Promise
$deferred = new ReactPromiseDeferred();
$promise = $deferred->promise()
->then(
function ($value) {
// Resolved, use $value
},
function ($reason) {
// Rejected, show or log $reason
},
function ($status) {
// Progress changed, show or log $status
}
);
ReactPHP – Promises example
Hostname lookup – the old way
$hostnames = explode(',', $_POST['hostnames']);
$hostnames = FilterDangerousHostnames($hostnames);
$success = array();
foreach ($hostnames as $hostname) {
$ip = gethostbyname($hostname);
if ($ip != $hostname) {
$success[] = “$hostname ($ip)”;
}
}
echo 'Success resolving ' . implode(', ', $success);
Sequential
→ 10 hostnames → 10 sequential lookups
DNS timeouts → delays
Hostname lookup – the async way
$loop = ReactEventLoopFactory::create();
$factory = new ReactDnsResolverFactory();
$dns = $factory->create('8.8.8.8', $loop);
$hostnames = explode(',', $_POST['hostnames']);
$hostnames = FilterDangerousHostnames($_POST['hostnames']);
$promises = array();
foreach ($hostnames as $hostname) {
$promises[] = $dns->resolve($hostname)
->then(
function($ip) use ($hostname) {
return "$hostname ($ip)";
},
function($error) { return ''; }
);
}
ReactPromiseall($promises)->then(
function($hostnames) {
$hostnames = array_filter($hostnames, 'strlen');
echo 'Success in resolving ' . implode(', ', $hostnames) . "n";
}
);
$loop->run();
ReactPHP – Chaining then() statements
$promise = $deferred->promise()
->then(
function ($a) {
return $a * 2;
}
)
->then(
function ($b) {
return $b * 2;
}
)
->then(
function ($c) {
echo 'c is now ' . $c;
}
);
$deferred->resolve(1); // Will output 'c is now 4'
ReactPHP – Chaining then() statements
$promise = $deferred->promise()
->then(
function ($a) {
if ($a > 5) {
return $a;
} else {
throw new Exception('Too small');
}
}
)
->then(
null,
function ($e) {
echo "We got this exception : " . $e->getMessage();
}
);
$deferred->resolve(10); // Will output nothing
$deferred->resolve(1); // Will output : We got this exception : Too small
ReactPHP – Promises vs Streams
Promises
→ Very useful
→ But : limited to simple return values
Streams
→ Much more powerful
→ Also somewhat more complex
ReactPHP - Streams
Either :
Readable
Writable
Both
Example :
Through stream = filter
Limited only by your imagination !
$loop = ReactEventLoopFactory::create();
$source = new ReactStreamStream(fopen('source.txt', 'r'), $loop);
$filter = new MyLibStreamAlnumFilter();
$dest = new ReactStreamStream(fopen('dest.txt', 'w'), $loop);
$source->pipe($filter)->pipe($dest);
$loop->run();
$loop = ReactEventLoopFactory::create();
$socket = new ReactSocketServer($loop);
$clients = new SplObjectStorage();
$i = 0;
$socket->on('connection', function($connection) use($clients, &$i) {
$connection->id = ++$i;
$connection->write('Enter your nickname: ');
$connection->on('data', function($message) use($clients, $connection) {
if (empty($connection->nickName)) {
$connection->nickName = $message;
} else {
foreach ($clients as $client) {
if ($client->id == $connection->id) {
continue;
}
$client->write(
sprintf(
'<%s> %s',
$connection->nickName,
$message
)
);
}
}
});
$clients->attach($connection);
});
$socket->listen(1337);
$loop->run();
Some golden rules & warnings
Golden rule #1 : asynchronous != faster code
Golden rule #2 : don't assume your code will remain as fast
Golden rule #3 : if you don't need a response, don't wait for one
Warning : async does not guarantee execution order !
Questions ?
Questions ?
Thanks !
@wimgtr
wim@cu.be
Please provide some feedback : http://joind.in/13259

More Related Content

What's hot (20)

PDF
ZeroMQ Is The Answer
Ian Barber
 
PPTX
Perl: Coro asynchronous
Shmuel Fomberg
 
ODP
My app is secure... I think
Wim Godden
 
ODP
My app is secure... I think
Wim Godden
 
PDF
ZeroMQ Is The Answer: DPC 11 Version
Ian Barber
 
PDF
How to stand on the shoulders of giants
Ian Barber
 
PDF
Asynchronous Programming FTW! 2 (with AnyEvent)
xSawyer
 
PDF
ZeroMQ: Messaging Made Simple
Ian Barber
 
PPTX
The Promised Land (in Angular)
Domenic Denicola
 
PDF
The Beauty Of Java Script V5a
rajivmordani
 
ODP
My app is secure... I think
Wim Godden
 
PDF
The Beauty of Java Script
Michael Girouard
 
PPTX
ES6 is Nigh
Domenic Denicola
 
PDF
YAPC::Asia 2010 Twitter解析サービス
Yusuke Wada
 
PDF
PHPCon 2016: PHP7 by Witek Adamus / XSolve
XSolve
 
PDF
Créer une base NoSQL en 1 heure
Amaury Bouchard
 
PDF
Introduction to Nodejs
Gabriele Lana
 
KEY
Node.js - Best practices
Felix Geisendörfer
 
PDF
Nodejs - A quick tour (v6)
Felix Geisendörfer
 
PDF
Web Crawling with NodeJS
Sylvain Zimmer
 
ZeroMQ Is The Answer
Ian Barber
 
Perl: Coro asynchronous
Shmuel Fomberg
 
My app is secure... I think
Wim Godden
 
My app is secure... I think
Wim Godden
 
ZeroMQ Is The Answer: DPC 11 Version
Ian Barber
 
How to stand on the shoulders of giants
Ian Barber
 
Asynchronous Programming FTW! 2 (with AnyEvent)
xSawyer
 
ZeroMQ: Messaging Made Simple
Ian Barber
 
The Promised Land (in Angular)
Domenic Denicola
 
The Beauty Of Java Script V5a
rajivmordani
 
My app is secure... I think
Wim Godden
 
The Beauty of Java Script
Michael Girouard
 
ES6 is Nigh
Domenic Denicola
 
YAPC::Asia 2010 Twitter解析サービス
Yusuke Wada
 
PHPCon 2016: PHP7 by Witek Adamus / XSolve
XSolve
 
Créer une base NoSQL en 1 heure
Amaury Bouchard
 
Introduction to Nodejs
Gabriele Lana
 
Node.js - Best practices
Felix Geisendörfer
 
Nodejs - A quick tour (v6)
Felix Geisendörfer
 
Web Crawling with NodeJS
Sylvain Zimmer
 

Viewers also liked (20)

PDF
Asynchronous processing with PHP and Symfony2. Do it simple
Kirill Chebunin
 
PPT
Asynchronous PHP. Myth? Reality!
Alexander Lisachenko
 
ODP
WebSockets with PHP: Mission impossible
Yoan-Alexander Grigorov
 
PDF
Scaling Symfony2 apps with RabbitMQ - Symfony UK Meetup
Kacper Gunia
 
PPTX
Writing and using php streams and sockets
Elizabeth Smith
 
PDF
php[world] 2016 - You Don’t Need Node.js - Async Programming in PHP
Adam Englander
 
PDF
ReactPHP: practical intro
Dennis Povshedny
 
PDF
Promise pattern
Sebastiaan Deckers
 
KEY
Time tested php with libtimemachine
Nick Galbreath
 
PDF
Running a Scalable And Reliable Symfony2 Application in Cloud (Symfony Sweden...
Ville Mattila
 
PPTX
20141011 mastering mysqlnd
do_aki
 
KEY
libinjection: a C library for SQLi detection, from Black Hat USA 2012
Nick Galbreath
 
KEY
libinjection: new technique in detecting SQLi attacks, iSEC Partners Open Forum
Nick Galbreath
 
PPTX
Program understanding: What programmers really want
Einar Høst
 
PDF
Zend con 2016 - Asynchronous Prorgamming in PHP
Adam Englander
 
PDF
Node.js interactive NA 2016: Tales From the Crypt
Adam Englander
 
PDF
Py Vegas - Tales from the crypt
Adam Englander
 
PPTX
IoT Lockdown
Adam Englander
 
PDF
php[world] 2016 - Tales From the Crypto: A Cryptography Primer
Adam Englander
 
PPTX
Python Bluetooth
Adam Englander
 
Asynchronous processing with PHP and Symfony2. Do it simple
Kirill Chebunin
 
Asynchronous PHP. Myth? Reality!
Alexander Lisachenko
 
WebSockets with PHP: Mission impossible
Yoan-Alexander Grigorov
 
Scaling Symfony2 apps with RabbitMQ - Symfony UK Meetup
Kacper Gunia
 
Writing and using php streams and sockets
Elizabeth Smith
 
php[world] 2016 - You Don’t Need Node.js - Async Programming in PHP
Adam Englander
 
ReactPHP: practical intro
Dennis Povshedny
 
Promise pattern
Sebastiaan Deckers
 
Time tested php with libtimemachine
Nick Galbreath
 
Running a Scalable And Reliable Symfony2 Application in Cloud (Symfony Sweden...
Ville Mattila
 
20141011 mastering mysqlnd
do_aki
 
libinjection: a C library for SQLi detection, from Black Hat USA 2012
Nick Galbreath
 
libinjection: new technique in detecting SQLi attacks, iSEC Partners Open Forum
Nick Galbreath
 
Program understanding: What programmers really want
Einar Høst
 
Zend con 2016 - Asynchronous Prorgamming in PHP
Adam Englander
 
Node.js interactive NA 2016: Tales From the Crypt
Adam Englander
 
Py Vegas - Tales from the crypt
Adam Englander
 
IoT Lockdown
Adam Englander
 
php[world] 2016 - Tales From the Crypto: A Cryptography Primer
Adam Englander
 
Python Bluetooth
Adam Englander
 
Ad

Similar to The promise of asynchronous PHP (20)

ODP
The promise of asynchronous PHP
Wim Godden
 
KEY
Mojo as a_client
Marcus Ramberg
 
PDF
Solid principles
Bastian Feder
 
PDF
When symfony met promises
Marc Morera
 
PDF
Sane Async Patterns
TrevorBurnham
 
PDF
Javascript: the important bits
Chris Saylor
 
PDF
Durian: a PHP 5.5 microframework with generator-style middleware
Kuan Yen Heng
 
PDF
Jakub Kulhán - ReactPHP + Symfony = PROFIT (1. sraz přátel Symfony v Praze)
Péhápkaři
 
KEY
Good Evils In Perl (Yapc Asia)
Kang-min Liu
 
PPTX
Java script for web developer
Chalermpon Areepong
 
PDF
Being functional in PHP
David de Boer
 
PDF
Why async and functional programming in PHP7 suck and how to get overr it?
Lucas Witold Adamus
 
PPTX
PHP PPT FILE
AbhishekSharma2958
 
PDF
Code Generation in PHP - PHPConf 2015
Lin Yo-An
 
PPT
PHP CLI: A Cinderella Story
Mike Lively
 
PPTX
Introducing PHP Latest Updates
Iftekhar Eather
 
PDF
Promises - Asynchronous Control Flow
Henrique Barcelos
 
PDF
Generating Power with Yield
Jason Myers
 
ODP
ES6 PPT FOR 2016
Manoj Kumar
 
PDF
Javascript & Ajax Basics
Richard Paul
 
The promise of asynchronous PHP
Wim Godden
 
Mojo as a_client
Marcus Ramberg
 
Solid principles
Bastian Feder
 
When symfony met promises
Marc Morera
 
Sane Async Patterns
TrevorBurnham
 
Javascript: the important bits
Chris Saylor
 
Durian: a PHP 5.5 microframework with generator-style middleware
Kuan Yen Heng
 
Jakub Kulhán - ReactPHP + Symfony = PROFIT (1. sraz přátel Symfony v Praze)
Péhápkaři
 
Good Evils In Perl (Yapc Asia)
Kang-min Liu
 
Java script for web developer
Chalermpon Areepong
 
Being functional in PHP
David de Boer
 
Why async and functional programming in PHP7 suck and how to get overr it?
Lucas Witold Adamus
 
PHP PPT FILE
AbhishekSharma2958
 
Code Generation in PHP - PHPConf 2015
Lin Yo-An
 
PHP CLI: A Cinderella Story
Mike Lively
 
Introducing PHP Latest Updates
Iftekhar Eather
 
Promises - Asynchronous Control Flow
Henrique Barcelos
 
Generating Power with Yield
Jason Myers
 
ES6 PPT FOR 2016
Manoj Kumar
 
Javascript & Ajax Basics
Richard Paul
 
Ad

More from Wim Godden (20)

PDF
Beyond php - it's not (just) about the code
Wim Godden
 
PDF
Bringing bright ideas to life
Wim Godden
 
PDF
The why and how of moving to php 8
Wim Godden
 
PDF
The why and how of moving to php 7
Wim Godden
 
PDF
My app is secure... I think
Wim Godden
 
PDF
My app is secure... I think
Wim Godden
 
PDF
Building interactivity with websockets
Wim Godden
 
PDF
Bringing bright ideas to life
Wim Godden
 
ODP
Your app lives on the network - networking for web developers
Wim Godden
 
ODP
The why and how of moving to php 7.x
Wim Godden
 
ODP
The why and how of moving to php 7.x
Wim Godden
 
ODP
Beyond php - it's not (just) about the code
Wim Godden
 
ODP
My app is secure... I think
Wim Godden
 
ODP
Building interactivity with websockets
Wim Godden
 
ODP
Your app lives on the network - networking for web developers
Wim Godden
 
ODP
My app is secure... I think
Wim Godden
 
ODP
Practical git for developers
Wim Godden
 
ODP
Is your code ready for PHP 7 ?
Wim Godden
 
ODP
Beyond php - it's not (just) about the code
Wim Godden
 
ODP
My app is secure... I think
Wim Godden
 
Beyond php - it's not (just) about the code
Wim Godden
 
Bringing bright ideas to life
Wim Godden
 
The why and how of moving to php 8
Wim Godden
 
The why and how of moving to php 7
Wim Godden
 
My app is secure... I think
Wim Godden
 
My app is secure... I think
Wim Godden
 
Building interactivity with websockets
Wim Godden
 
Bringing bright ideas to life
Wim Godden
 
Your app lives on the network - networking for web developers
Wim Godden
 
The why and how of moving to php 7.x
Wim Godden
 
The why and how of moving to php 7.x
Wim Godden
 
Beyond php - it's not (just) about the code
Wim Godden
 
My app is secure... I think
Wim Godden
 
Building interactivity with websockets
Wim Godden
 
Your app lives on the network - networking for web developers
Wim Godden
 
My app is secure... I think
Wim Godden
 
Practical git for developers
Wim Godden
 
Is your code ready for PHP 7 ?
Wim Godden
 
Beyond php - it's not (just) about the code
Wim Godden
 
My app is secure... I think
Wim Godden
 

Recently uploaded (20)

PDF
Economic Impact of Data Centres to the Malaysian Economy
flintglobalapac
 
PDF
GDG Cloud Munich - Intro - Luiz Carneiro - #BuildWithAI - July - Abdel.pdf
Luiz Carneiro
 
PPTX
Dev Dives: Automate, test, and deploy in one place—with Unified Developer Exp...
AndreeaTom
 
PDF
State-Dependent Conformal Perception Bounds for Neuro-Symbolic Verification
Ivan Ruchkin
 
PPTX
Farrell_Programming Logic and Design slides_10e_ch02_PowerPoint.pptx
bashnahara11
 
PPTX
AI in Daily Life: How Artificial Intelligence Helps Us Every Day
vanshrpatil7
 
PDF
AI Unleashed - Shaping the Future -Starting Today - AIOUG Yatra 2025 - For Co...
Sandesh Rao
 
PDF
RAT Builders - How to Catch Them All [DeepSec 2024]
malmoeb
 
PPTX
Agile Chennai 18-19 July 2025 Ideathon | AI Powered Microfinance Literacy Gui...
AgileNetwork
 
PDF
introduction to computer hardware and sofeware
chauhanshraddha2007
 
PPTX
Simple and concise overview about Quantum computing..pptx
mughal641
 
PDF
TrustArc Webinar - Navigating Data Privacy in LATAM: Laws, Trends, and Compli...
TrustArc
 
PDF
Researching The Best Chat SDK Providers in 2025
Ray Fields
 
PPTX
Agentic AI in Healthcare Driving the Next Wave of Digital Transformation
danielle hunter
 
PDF
Research-Fundamentals-and-Topic-Development.pdf
ayesha butalia
 
PPTX
AI and Robotics for Human Well-being.pptx
JAYMIN SUTHAR
 
PDF
NewMind AI Weekly Chronicles – July’25, Week III
NewMind AI
 
PDF
Per Axbom: The spectacular lies of maps
Nexer Digital
 
PPTX
AI Code Generation Risks (Ramkumar Dilli, CIO, Myridius)
Priyanka Aash
 
PDF
CIFDAQ's Market Wrap : Bears Back in Control?
CIFDAQ
 
Economic Impact of Data Centres to the Malaysian Economy
flintglobalapac
 
GDG Cloud Munich - Intro - Luiz Carneiro - #BuildWithAI - July - Abdel.pdf
Luiz Carneiro
 
Dev Dives: Automate, test, and deploy in one place—with Unified Developer Exp...
AndreeaTom
 
State-Dependent Conformal Perception Bounds for Neuro-Symbolic Verification
Ivan Ruchkin
 
Farrell_Programming Logic and Design slides_10e_ch02_PowerPoint.pptx
bashnahara11
 
AI in Daily Life: How Artificial Intelligence Helps Us Every Day
vanshrpatil7
 
AI Unleashed - Shaping the Future -Starting Today - AIOUG Yatra 2025 - For Co...
Sandesh Rao
 
RAT Builders - How to Catch Them All [DeepSec 2024]
malmoeb
 
Agile Chennai 18-19 July 2025 Ideathon | AI Powered Microfinance Literacy Gui...
AgileNetwork
 
introduction to computer hardware and sofeware
chauhanshraddha2007
 
Simple and concise overview about Quantum computing..pptx
mughal641
 
TrustArc Webinar - Navigating Data Privacy in LATAM: Laws, Trends, and Compli...
TrustArc
 
Researching The Best Chat SDK Providers in 2025
Ray Fields
 
Agentic AI in Healthcare Driving the Next Wave of Digital Transformation
danielle hunter
 
Research-Fundamentals-and-Topic-Development.pdf
ayesha butalia
 
AI and Robotics for Human Well-being.pptx
JAYMIN SUTHAR
 
NewMind AI Weekly Chronicles – July’25, Week III
NewMind AI
 
Per Axbom: The spectacular lies of maps
Nexer Digital
 
AI Code Generation Risks (Ramkumar Dilli, CIO, Myridius)
Priyanka Aash
 
CIFDAQ's Market Wrap : Bears Back in Control?
CIFDAQ
 

The promise of asynchronous PHP

  • 1. The promise of asynchronous PHP Wim Godden Cu.be Solutions @wimgtr
  • 2. Who am I ? Wim Godden (@wimgtr)
  • 11. Belgium – the traffic
  • 12. Who am I ? Wim Godden (@wimgtr) Founder of Cu.be Solutions (http://cu.be) Open Source developer since 1997 Developer of OpenX, PHPCompatibility, PHPConsistent, ... Speaker at Open Source conferences
  • 13. Who are you ? Developers ? Ever worked with asynchronous PHP libraries ? Node.JS ?
  • 16. Blocking I/O Disk reading/writing Network reading/writing Communication with DB (with some exceptions) Sending mail ...
  • 17. Non-blocking = good Work on multiple things at same time Not entirely sequential anymore How do you know something is finished ? → Events !
  • 19. Callback hell $one->do(function ($two) { $two->do(function ($three) { $three->do(function ($stillcounting) { $stillcounting->get(function() { throw new IQuitException(); }); }); }); });
  • 20. State of asynchronous PHP Several built-in functions Several libraries (using the built-in functions) Facebook Hack
  • 22. Pthreads class WebRequest extends Thread { public $url; public $response; public function __construct($url){ $this->url = $url; } public function run() { $this->response = file_get_contents($this->url); } } $request = new WebRequest("http://cu.be"); if ($request->start()) { /* do some work here */ $a = array_fill(0, 10000000, 'test'); for ($i = 0; $i < count($a); $i++) {} /* ensure we have data */ $request->join(); var_dump($request->response); }
  • 23. pcntl_fork Clones PHP process Multiprocessing, not multithreading No communication between processes No Apache
  • 24. popen child.php <?php /* Do some work */ echo 'Output here'; main.php <?php // open child process $child = popen('php child.php', 'r'); /* * Do some work, while already doing other * work in the child process. */ // get response from child (if any) as soon at it's ready: $response = stream_get_contents($child); W arning : doesn't behave sam e on all operating system s !
  • 25. curl_multi_select $ch1 = curl_init(); $ch2 = curl_init(); curl_setopt($ch1, CURLOPT_URL, "http://www.google.com/"); curl_setopt($ch2, CURLOPT_URL, "http://www.yahoo.com/"); $mh = curl_multi_init(); curl_multi_add_handle($mh,$ch1); curl_multi_add_handle($mh,$ch2); $active = null; do { do { $mrc = curl_multi_exec($mh, $active); } while ($mrc == CURLM_CALL_MULTI_PERFORM); usleep(1000); } while (curl_multi_select($mh) === -1); while ($active && $mrc == CURLM_OK) { if (curl_multi_select($mh) != -1) { do { $mrc = curl_multi_exec($mh, $active); } while ($mrc == CURLM_CALL_MULTI_PERFORM); } } curl_multi_remove_handle($mh, $ch1); curl_multi_remove_handle($mh, $ch2); curl_multi_close($mh);
  • 26. Libevent, libev, libuv Event handling libraries PHP extensions libevent = also used by Memcached libev = not available on Windows
  • 27. Using Curl as async system $c = curl_init(); curl_setopt($c, CURLOPT_URL, 'http://www.long.process.com/calling- here?action=go&from=4&to=40000'); curl_setopt($c, CURLOPT_FOLLOW_LOCATION, true); curl_setopt($c, CURLOPT_FRESH_CONNECT, true); curl_setopt($c, CURLOPT_TIMEOUT_MS, 1); curl_exec($c); curl_close($c); // Code continues after 1ms timeout
  • 28. ReactPHP Event-driven non-blocking I/O library Written in PHP Provides event-driven interface Implements event loop
  • 29. ReactPHP – a simple webserver $loop = new ReactEventLoopFactory::create(); $socket = new ReactSocketServer($loop); $http = new ReactHttpServer($socket, $loop); $http->on('request', function ($request, $response) { $response->writeHead(200); $response->end("Hello world!n"); }); $socket->listen(80); $loop->run();
  • 30. ReactPHP - structure Event Loop Stream Socket HTTP → stream_select() / libevent / libev
  • 31. ReactPHP - structure Event Loop Stream Socket HTTPClient DNSWHOIS HTTPClient WebsocketSOCKS IRC
  • 32. ReactPHP – Deferred & Promise Computation to be performed = Deferred (ReactPromiseDeferred) 2 possible status : Resolved Rejected
  • 33. ReactPHP – Deferred & Promise $deferred = new ReactPromiseDeferred(); $promise = $deferred->promise() ->then( function ($value) { // Resolved, use $value }, function ($reason) { // Rejected, show or log $reason }, function ($status) { // Progress changed, show or log $status } );
  • 35. Hostname lookup – the old way $hostnames = explode(',', $_POST['hostnames']); $hostnames = FilterDangerousHostnames($hostnames); $success = array(); foreach ($hostnames as $hostname) { $ip = gethostbyname($hostname); if ($ip != $hostname) { $success[] = “$hostname ($ip)”; } } echo 'Success resolving ' . implode(', ', $success); Sequential → 10 hostnames → 10 sequential lookups DNS timeouts → delays
  • 36. Hostname lookup – the async way $loop = ReactEventLoopFactory::create(); $factory = new ReactDnsResolverFactory(); $dns = $factory->create('8.8.8.8', $loop); $hostnames = explode(',', $_POST['hostnames']); $hostnames = FilterDangerousHostnames($_POST['hostnames']); $promises = array(); foreach ($hostnames as $hostname) { $promises[] = $dns->resolve($hostname) ->then( function($ip) use ($hostname) { return "$hostname ($ip)"; }, function($error) { return ''; } ); } ReactPromiseall($promises)->then( function($hostnames) { $hostnames = array_filter($hostnames, 'strlen'); echo 'Success in resolving ' . implode(', ', $hostnames) . "n"; } ); $loop->run();
  • 37. ReactPHP – Chaining then() statements $promise = $deferred->promise() ->then( function ($a) { return $a * 2; } ) ->then( function ($b) { return $b * 2; } ) ->then( function ($c) { echo 'c is now ' . $c; } ); $deferred->resolve(1); // Will output 'c is now 4'
  • 38. ReactPHP – Chaining then() statements $promise = $deferred->promise() ->then( function ($a) { if ($a > 5) { return $a; } else { throw new Exception('Too small'); } } ) ->then( null, function ($e) { echo "We got this exception : " . $e->getMessage(); } ); $deferred->resolve(10); // Will output nothing $deferred->resolve(1); // Will output : We got this exception : Too small
  • 39. ReactPHP – Promises vs Streams Promises → Very useful → But : limited to simple return values Streams → Much more powerful → Also somewhat more complex
  • 40. ReactPHP - Streams Either : Readable Writable Both Example : Through stream = filter Limited only by your imagination ! $loop = ReactEventLoopFactory::create(); $source = new ReactStreamStream(fopen('source.txt', 'r'), $loop); $filter = new MyLibStreamAlnumFilter(); $dest = new ReactStreamStream(fopen('dest.txt', 'w'), $loop); $source->pipe($filter)->pipe($dest); $loop->run();
  • 41. $loop = ReactEventLoopFactory::create(); $socket = new ReactSocketServer($loop); $clients = new SplObjectStorage(); $i = 0; $socket->on('connection', function($connection) use($clients, &$i) { $connection->id = ++$i; $connection->write('Enter your nickname: '); $connection->on('data', function($message) use($clients, $connection) { if (empty($connection->nickName)) { $connection->nickName = $message; } else { foreach ($clients as $client) { if ($client->id == $connection->id) { continue; } $client->write( sprintf( '<%s> %s', $connection->nickName, $message ) ); } } }); $clients->attach($connection); }); $socket->listen(1337); $loop->run();
  • 42. Some golden rules & warnings Golden rule #1 : asynchronous != faster code Golden rule #2 : don't assume your code will remain as fast Golden rule #3 : if you don't need a response, don't wait for one Warning : async does not guarantee execution order !
  • 45. Thanks ! @wimgtr [email protected] Please provide some feedback : http://joind.in/13259