Exploring the New PHP 8.1 Fibers Feature for Concurrency
Written on
Chapter 1: Introduction to PHP 8.1 Fibers
As PHP strives to enhance its functionality, the introduction of Fibers stands out as a significant upgrade. Set to launch with PHP 8.1, Fibers will bring a form of asynchronous programming, known as coroutines, into the PHP ecosystem.
Fibers can be understood as lightweight threads of execution that operate in a seemingly parallel manner. While they appear to run concurrently, the PHP runtime manages them rather than the CPU directly. Various programming languages implement similar concepts, all aimed at allowing the computer to handle multiple tasks simultaneously and wait until all are completed.
It’s important to note that the incorporation of Fibers doesn't lead to true asynchronous processing in PHP. The core of PHP will still function synchronously even after Fibers are introduced. You can think of using Fibers as switching between vehicles; while you can drive multiple cars, only one is in motion at a time.
How Do Fibers Operate?
A Fiber is defined as a single final class, comparable to a car that can start, pause, and resume its journey. When you initialize a Fiber instance with a callable function, nothing occurs until the Fiber is activated, triggering the callback just like any standard PHP code.
$fiber = new Fiber(function() : void {
echo "I'm running a Fiber, yay!";
});
$fiber->start(); // Output: I'm running a Fiber, yay!
Despite the asynchronous label, calling Fiber::suspend() within the callback pauses the execution and yields control back to the main thread. However, the Fiber remains active, awaiting a resume command.
$fiber = new Fiber(function() : void {
Fiber::suspend();
echo "I'm running a Fiber, yay!";
});
$fiber->start(); // No output occurs at this stage
Now that the Fiber is suspended, to continue its execution, you would invoke the resume() method externally. Although this isn't true asynchronous behavior, it allows your application to manage two tasks at once. The critical aspect here is that the state of the Fiber is preserved, enabling a switch between tasks seamlessly.
One of the remarkable features of start(), suspend(), and resume() is that they can accept arguments. The start() method can pass arguments to the callable and returns whatever the suspend() method receives. Conversely, suspend() returns values that resume() receives.
This simplifies communication between the main thread and the Fiber:
- resume() feeds values into the Fiber sourced from suspend()
- suspend() exports values received by resume()
When executing the above code, you might observe something like:
Value from fiber suspending: fiber
Value used to resume fiber: test
Chapter 2: Enhancing PHP's Capabilities
The first video titled "What is the PHP 8.1 Fibers Feature? I'll explain you EVERYTHING!" provides an in-depth look into how Fibers will function and their potential impact on PHP development.
PHP is typically paired with nginx or Apache, primarily due to its non-multithreaded nature. The built-in server in PHP is blocking and serves mainly for testing purposes. The introduction of Fibers could transform how PHP interacts with sockets, allowing for more efficient operations, such as WebSockets, server-side events, and pooled database connections, without needing to compile extensions or resort to complex workarounds.
While these advancements may take time to fully integrate, the promise of a unified code base for additional features without extensive compilation efforts is certainly appealing.
You Likely Won't Use Fibers Directly
According to PHP documentation, Fibers provide only the essential functionality for developers to implement full-stack coroutines or green threads. Unless there's a specific reason to interact directly with them, developers won't engage with Fibers in the same way as with coroutines in languages like JavaScript or Go.
High-level frameworks such as Symfony, Laravel, and CakePHP will require time to adapt to Fibers and develop tools that facilitate their use from a developer's perspective. Conversely, low-level frameworks like amphp and ReactPHP have already begun integrating Fibers into their latest versions.
The standardization of Fibers means that various frameworks will develop their unique concurrency solutions, each with its benefits and drawbacks.
Only One Fiber at a Time
According to Aaron Piotrowski from the PHP Internals Podcast, "Since only one Fiber can be executing at the same time, you don't encounter the same race conditions that occur when memory is accessed or modified by two threads."
Frameworks will need to address concurrency and synchronization challenges within shared memory spaces. This alleviates the need to manage data races, semaphores, and mutexes, issues that developers in languages like Go must navigate. However, the limitation remains that only two operations can be managed simultaneously.
No Channels in the Meantime
While multiple Fibers can be declared, only one can run at a time, eliminating synchronization issues. However, there is a risk that another Fiber could overwrite data shared by the first. One potential solution is to adopt a channel system akin to Go's.
Derick Rethans asked about the potential for channels, and Aaron suggested that additional implementations must accompany Fibers. Until then, frameworks will dictate how channels are used, should they see fit, much like the development seen in amphp.
Comparing with Other Languages
The Go programming language has gained significant popularity in recent months due to its inherent focus on concurrency. With the go keyword, developers can execute tasks concurrently, utilizing mutexes or channels for synchronization, making it straightforward to work with.
names := make(chan string)
go doFoo(names)
go doBar(names)
From this perspective, Go is far ahead of PHP’s nascent concurrency model. For those seeking robust multithreading capabilities, languages like Go or Rust are preferable.
While PHP is not incompatible with concurrency models, its architecture remains fundamentally synchronous, which may hinder convenience and clarity. For PHP to achieve true concurrency like Go, it would require a complete overhaul, paving the way for a multitude of possibilities in a computing landscape that has embraced multithreading.
In closing, the future seems bright for PHP with the advent of Fibers, and there is hope for a greater focus on innovative features and independence in the language's development.
The second video titled "5 Exciting New Features in PHP 8.1" showcases not only Fibers but other noteworthy enhancements, providing further insights into what developers can look forward to in PHP 8.1.