From ReactPHP to Facebook Hack's Async implementation and many more, asynchronous programming has been a 'hot' topic lately. But how well does async programming support work in PHP and what can you actually use it for in your projects ? Let's look at some real-world use cases and how they leverage the power of async to do things you didn't know PHP could do.
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 ?
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);
}
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
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
}
);
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();
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 !