Cees-Jan

- Post source at 🐙

ReactPHP: Ticks

The simplest feature in ReactPHP are ticks. Just as timers they are part of the event-loop. Ticks are often referred to as deferred callbacks. This makes them very useful to utilize the window between I/O events.

Newton's Cradle

Installation

Since ticks come with the event-loop no extra package is required to install them.

Tick Queue

Each time you call nextTick or futureTick the passed callback is pushed into a SplQueue. Once the event-loop is done handling the current outstanding I/O it will start processing the tick queues. (Note that the exact workings of an event loop differ per type of event loop. We'll go into that later this month.)

Next vs. Future

Ticks come in two flavours: next and future. Next will continue running until all callbacks on the SplQueue are executed. While future will only execute the callbacks that are on the SplQueue when it begins to process them. This means that next will also execute new callbacks you push onto the queue while future doesn't. This makes both ticks types really useful in situations where you need to make a short but blocking call and firing a child process is a waste of resources. A short blocking call in this case would be something computing intensive like oauth.

A simple example

Lets start by demonstrating the difference between next ticks and future ticks

Future ticks

The future ticks in this example won’t block the loop and everything stops after one 10th of a second.

$loop->addTimer(0.1, function () use ($loop) {
    $loop->stop();
});

function fooBar($loop) {
    return function () use ($loop) {
        echo 'a';
        $loop->futureTick(fooBar($loop));
    };
}

$loop->futureTick(fooBar($loop));
$loop->run();
Next Ticks

How ever when we use the same code but do a next tick instead it will continue running.

$loop->addTimer(0.1, function () use ($loop) {
    $loop->stop();
});

function fooBar($loop) {
    return function () use ($loop) {
        echo 'a';
        $loop->nextTick(fooBar($loop));
    };
}

$loop->nextTick(fooBar($loop));
$loop->run();

And that is really all there is to ticks.

Community examples

This week's community examples concerto/comms and recoil/recoil use ticks to defer callback execution to a more appropriate time.

concerto/comms

usebeagle/comms is a package providing inter-process communication over Unix domain sockets. It uses a tick to defer the closing of a server connection.

recoil/recoil

recoil/recoil is a generator-based cooperative multitasking kernel. Instead of exposing the promise API it utilizes generators to return values through coroutines. (Really cool stuff be sure to check it out!) Internally it uses ticks to check and process internal state after I/O has happened.

Examples

All the examples from this post can be found on Github.

Conclusion

Ticks are a simple but useful feature. Providing the possibility to defer a callback's execution until after the I/O queue has been done. That window of opportunity is for example perfect to (d)e(n)code some json, sign a request to twitter or hand the control to any other possible blocking code. But keep in mind that when you're blocking for to long you're blocking I/O.


Categories: PHP - ReactPHP - ReactPHP Series Tags: ReactPHP - Ticks - PHP