Software Development

Developing asynchronous applications in PHP – part II

Grudzień 2, 2015 3
There is a thin line between awesome code and a total mess and I think coroutines sit exactly on that line.
Podziel się:

In the first part of the series I introduced ideas of cooperative multitasking, generators and yield keyword. You were also able to learn a bit about generator return expressions and I showed how yield can be used to interrupt linear flow of execution.

Next example shows how another brand new feature can be used – generator delegation:

/**
 * Generator
 * @return string
 */
$generatorWithTwoWayCommunication = function()
{
    $randomValue = mt_rand();
    yield $randomValue;
    $receivedFromOuterSpace = yield;
    $returnValue = yield from subGenerator($receivedFromOuterSpace, $randomValue);
    return $returnValue;
};

/**
 * Subgenerator
 * @return string
 */
function subGenerator($valueFromOuterSpace, $randomValue)
{
    yield $valueFromOuterSpace * $valueFromOuterSpace;
    yield $valueFromOuterSpace * $randomValue;
    return 'Lis Witalis';
};

/**
 * Main flow
 */
$generator = $generatorWithTwoWayCommunication();
$valueFromFirstIteration = $generator->current();
$generator->next();
$valueFromSecondIteration = $generator->send(666);
$generator->next();
$valueFromThirdIteration = $generator->current();
$generator->next();
$valueReturnedFromGenerator = $generator->getReturn();

The image below explains the execution flow of generator delegation example.

Coroutine example flow II

Coroutine example utilising generator return expression and generator delegation

As you can see it seems to be possible to develop asynchronous application in PHP. There is however quite an important PHP property that might be easily overseen when you start thinking about implementing Generator-base coroutines. The trap is hidden in Listing 2 in the first part and consists of a single line:

stream_set_blocking($socket, 0);

When you overcome unfriendliness of Generators and coroutines implementation and you start thinking about implementing them in your application then you will suddenly realise that the biggest obstacle to write asynchronous code in PHP lies elsewhere: PHP is synchronous by its very nature and virtually all the streams that are opened with defaults settings (including sockets) are blocking. It means that your options to make use of coroutines efficiently are limited to some solutions that are available in the wild and very few that are baked into PHP.

The most obvious example of asynchronous PHP framework is probably React. It supports basically all the stream operations but is still limited to user land code. Guzzle 6 is quite a decent option too but same limitations apply and you are required to implement quite a lot of logic on our own. Various C extensions that offer joy of asynchronism are pretty similar – Swoole will not miraculously make PHP stream asynchronous.

If you try to send asynchronous requests to the database (and you are not too keen to implement your own client library in pure PHP) then you are limited to mysqli with mysqlnd (for MySQL) and pg_send_query function (for Postgresql). None of other database drivers or extensions (including PDO) supports asynchronous operations. When you realise that one of the very first asynchronous features implemented in Hack was MySQL support then you may come to a conclusion that writing this very type of applications in PHP is not the best idea.

I wholeheartedly agree with the finding. Developing asynchronous applications in PHP does not seem to be a feasible option. There are lots of other languages out there that support asynchronism to great extent. If you want to stick to PHP ecosystem then Hack might be a decent option. You should keep in mind that this is still a project that mainly Facebook developers contribute to and it’s hard to predict its future (Wikimedia Foundation move to HHVM is an encouraging decision however). Hack supports asynchronous memcached and MySQL communication as well as various I/O operations.

If you prefered to try enterprise solution then .Net framework is one of the options available. You will get asynchronous HTTP requests, and file operations, and sound and video capture, and image file manipulation out of the box. Using AsyncPattern should allow you to achieve much more and, as far as I understand from what documentation states, one should be able to desynchronise majority of the code (as long as sockets do not block).

You will find even more opportunities in the world of JVM. Java offers Future interface that can represent result of an asynchronous call. If you wish to develop complex applications you may want to take a look at Akka framework (that implements its own version of futures) which is focused on concurrent applications and is non-blocking by design.

There is yet another option out there that seems to be the most feasible one when it comes to asynchrony. Asynchronous operations have been core to many web applications for a while. They were available on the client side first but since 2009 Node.js has been publicly available. V8 performance combined with Javascript non-blocking character are, in my opinion, the best solution money can buy for asynchronous web development as of now.

When you start thinking about adding asynchronous features to PHP application that you develop you should keep in mind that it will increase complexity of your platform. Even if you follow my advice and give up PHP for some functionalities then you will have to introduce microservice (or microservices) to be able to use additional language on a back end. If you are really sure that you want your product to utilise asynchrony then you should make this decision at an early stage as chosing wrong platform might affect your project’s future. PHP is great language but Popov’s words about generators and coroutines should be kept in mind:

There is a thin line between awesome code and a total mess and I think coroutines sit exactly on that line.

Sources and further reading:

4 / 5
Tagi: ,
Maciej Iwanowski
Autor: Maciej Iwanowski
Developer, fan of TDD, train-spotter, one-time poet. Co-founder of 3cloud.io and co-organizer of Tricity AWS User Group Poland. Interested in concurrency and distributed system. Devotee of third wave of coffee.

Imię i nazwisko (wymagane)

Adres email (wymagane)

Temat

Treść wiadomości

komentarze(3)

avatar'
thiet ke noi that biet thu
18 stycznia 2016 Odpowiedz

Hi friends, its wonderful piece of writing on the
topic of educationand completely defined, keep it up all the
time.

avatar'
thiet ke noi that biet thu
19 stycznia 2016 Odpowiedz

Quality articles is the crucial to attract the users to go to see the web page, that's what this web site is providing.

avatar'
Kendrick Perkins
20 stycznia 2016 Odpowiedz

Pretty element of content. I simply stumbled upon your weblog and in accession capital to claim that I get in fact loved account
your weblog posts. Any way I'll be subscribing to your augment
and even I fulfillment you get admission to constantly quickly.

Zostaw komentarz