php fibers
php fibers

The ability to efficiently execute multiple tasks concurrently is a vital aspect of modern web development. While PHP has traditionally lacked built-in support for multi-threading, the introduction of fibers in PHP 8.1.0 offers a game-changing solution. Fibers are lightweight, full-stack coroutines that enable developers to suspend and resume function execution, simulating multi-threading behavior and enhancing the overall efficiency of web applications. In this article, we will delve into the essentials of PHP fibers, explore their usage, and demonstrate how they can significantly improve your web development projects.

In this article, we will explore the basics of PHP fibers and learn how to use them to improve the efficiency of our web development projects. We will cover everything from creating a fiber to more advanced features, so you can start leveraging the power of fibers in your own PHP projects.

Fibers are lightweight, full-stack coroutines that allow suspending the current execution of a function and resuming it later, which makes it possible to achieve multi-threading-like behavior. In this article, we will go over the basics of PHP fibers and how to use them.

Creating a php fiber

A fiber is created using the Fiber class. Here is an example of how to create a fiber that echoes a message:

phpCopy code$fiber = new Fiber(function() {
    echo "Hello from the fiber\n";
});

$fiber->start();

In this example, we create a new fiber by passing a callable function to the Fiber constructor. The function is not executed yet, but when we call the start() method, the function will be executed in a new fiber.

Suspending and resuming a php fiber

Fibers can be paused at any point using the Fiber::suspend() method. This method accepts an optional value that can be used to resume the fiber later. Here is an example of how to suspend and resume a fiber:

phpCopy code$fiber = new Fiber(function() {
    echo "Fiber started\n";
    Fiber::suspend("Value passed to resume\n");
    echo "Fiber resumed\n";
});

$fiber->start();
echo "Fiber suspended with value: " . $fiber->getCurrentValue() . "\n";
$fiber->resume();

In this example, we create a new fiber that echoes “Fiber started”, suspends itself using Fiber::suspend(), and echoes “Fiber resumed” when it is resumed. We start the fiber, and it prints “Fiber started”. We then get the current value of the fiber using getCurrentValue(), which should return null because the fiber is suspended. Finally, we resume the fiber, and it prints “Fiber resumed” and exits.

Passing values to a php fiber

When a fiber is started, it can accept an optional parameter that is passed to the callable function. Here is an example of how to pass a parameter to a fiber:

phpCopy code$fiber = new Fiber(function($name) {
    echo "Hello $name\n";
});

$fiber->start("John");

In this example, we create a new fiber that accepts a parameter called “name” and echoes “Hello $name”. We start the fiber with the parameter “John”, and it prints “Hello John”.

Creating simple rate-limited API request system using PHP fibers

In this example, we’ll create a simple rate-limited API request system using PHP fibers. We’ll be sending requests to an API with a limit of 5 requests per second. If the limit is reached, fibers will help us pause the execution until we can send the next request.

<?php

use \Fiber;

class RateLimiter {
    private int $maxRequestsPerSecond;
    private float $lastRequestTime;
    private Fiber $limiter;

    public function __construct(int $maxRequestsPerSecond) {
        $this->maxRequestsPerSecond = $maxRequestsPerSecond;
        $this->lastRequestTime = microtime(true);

        $this->limiter = new Fiber(function () {
            while (true) {
                $currentTime = microtime(true);
                $timeSinceLastRequest = $currentTime - $this->lastRequestTime;

                if ($timeSinceLastRequest < 1 / $this->maxRequestsPerSecond) {
                    usleep((int) ((1 / $this->maxRequestsPerSecond - $timeSinceLastRequest) * 1000000));
                }

                $this->lastRequestTime = microtime(true);
                Fiber::suspend();
            }
        });

        $this->limiter->start();
    }

    public function request(callable $apiCall) {
        $this->limiter->resume();
        return $apiCall();
    }
}

$rateLimiter = new RateLimiter(5);

$apiCall = function () {
    // Simulate an API call
    echo "API request sent at " . microtime(true) . PHP_EOL;
};

for ($i = 0; $i < 10; $i++) {
    $rateLimiter->request($apiCall);
}

Running this example will give something like :

$ php rate-limiter-api.php
API request sent at 1678996902.2899
API request sent at 1678996902.4936
API request sent at 1678996902.6969
API request sent at 1678996902.8985
API request sent at 1678996903.1006
API request sent at 1678996903.3031
API request sent at 1678996903.5055
API request sent at 1678996903.7094
API request sent at 1678996903.9142
API request sent at 1678996904.116

In this example, we have a RateLimiter class that takes the maximum number of requests per second as a parameter. It has a request method that takes a callable representing the API call. The rate limiter ensures that we don’t exceed the allowed number of requests per second by using fibers to pause the execution if necessary.

When the RateLimiter object is created, it starts a fiber that runs in an infinite loop. Inside the loop, it checks the time since the last request and sleeps if it’s too soon to send the next request. After sleeping, it updates the last request time and suspends the fiber.

When the request method is called, it resumes the fiber, which ensures we don’t exceed the rate limit. After the fiber is resumed, it calls the API function provided.

The example demonstrates how PHP fibers can be used to solve real-world problems like rate limiting in a simple and efficient manner.

Conclusion

In conclusion, fibers introduce a powerful and efficient mechanism for concurrent programming in PHP. This article provided an overview of PHP fibers, covering fundamental aspects like creating, suspending, and resuming fibers, as well as passing values to them. We also demonstrated a practical use case by implementing a rate-limited API request system. To further harness the potential of fibers, we encourage you to delve into the official documentation and experiment with this feature in your PHP projects.

LEAVE A REPLY

Please enter your comment!
Please enter your name here