rfc:fibers

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
rfc:fibers [2021/03/08 17:08]
trowski Update stubs
rfc:fibers [2021/07/12 21:30] (current)
kelunik
Line 3: Line 3:
   * Date: 2021-03-08   * Date: 2021-03-08
   * Authors: Aaron Piotrowski <trowski@php.net>, Niklas Keller <kelunik@php.net>   * Authors: Aaron Piotrowski <trowski@php.net>, Niklas Keller <kelunik@php.net>
-  * Status: Under Discussion+  * Status: Implemented
   * First Published at: http://wiki.php.net/rfc/fibers   * First Published at: http://wiki.php.net/rfc/fibers
  
 ===== Introduction ===== ===== Introduction =====
  
-For most of PHP’s history, people have written PHP code only as synchronous code. They have code that runs synchronously and in turn, only calls functions that run synchronously. Synchronous functions stop execution until a result is available to return from the function.+For most of PHP’s history, people have written PHP code only as synchronous code. Execution of functions stops until a result is available to return from the function, including for I/O operations, which can be quite slow.
  
-More recently, there have been multiple projects that have allowed people to write asynchronous PHP code. Asynchronous functions accept a callback or return a placeholder for a future value (such as a promise) to run code at a future time once the result is available. Execution continues without waiting for a result. Examples of these projects are [[https://amphp.org/|amphp]], [[https://reactphp.org/|ReactPHP]], and [[https://guzzlephp.org/|Guzzle]].+More recently, there have been multiple projects that have allowed people to write asynchronous PHP code to allow for concurrent I/O operations. Asynchronous functions accept a callback or return a placeholder for a future value (such as a promise) to run code at a future time once the result is available. Execution continues without waiting for a result. Examples of these projects are [[https://amphp.org/|amphp]], [[https://reactphp.org/|ReactPHP]], and [[https://guzzlephp.org/|Guzzle]].
  
 The problem this RFC seeks to address is a difficult one to explain, but can be referred to as the [[https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function/|“What color is your function?”]] problem. The problem this RFC seeks to address is a difficult one to explain, but can be referred to as the [[https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function/|“What color is your function?”]] problem.
Line 18: Line 18:
   * Asynchronous functions change the way the function must be called.   * Asynchronous functions change the way the function must be called.
   * Synchronous functions may not call an asynchronous function (though asynchronous functions may call synchronous functions).   * Synchronous functions may not call an asynchronous function (though asynchronous functions may call synchronous functions).
-  * Calling an asynchronous function requires the entire callstack to be asynchronous+  * Calling an asynchronous function requires the entire call stack to be asynchronous
  
-For people who are familiar with using promises and await/yield to achieve writing asynchronous code, the problem can be expressed as: “Once one function returns a promise somewhere in your call stack, the entire call stack needs to return a promise because the result of the call cannot be known until the promise is resolved.”+For people who are familiar with using promises and/or await/yield to achieve writing asynchronous code, the problem can be expressed as: “Once one function returns a promise somewhere in your call stack, the entire call stack needs to return a promise because the result of the call cannot be known until the promise is resolved.”
  
 This RFC seeks to eliminate the distinction between synchronous and asynchronous functions by allowing functions to be interruptible without polluting the entire call stack. This would be achieved by: This RFC seeks to eliminate the distinction between synchronous and asynchronous functions by allowing functions to be interruptible without polluting the entire call stack. This would be achieved by:
Line 27: Line 27:
   * Adding a ''Fiber'' class and the corresponding reflection class ''ReflectionFiber''.   * Adding a ''Fiber'' class and the corresponding reflection class ''ReflectionFiber''.
   * Adding exception classes ''FiberError'' and ''FiberExit'' to represent errors.   * Adding exception classes ''FiberError'' and ''FiberExit'' to represent errors.
 +
 +Fibers allow for transparent non-blocking I/O implementations of existing interfaces (such as PSR-7, Doctine ORM, etc.). This is because the placeholder (promise) object is eliminated. Functions instead can declare the I/O result type instead of a placeholder object which cannot specify a resolution type because PHP does not support generics.
  
 ==== Fibers ==== ==== Fibers ====
Line 47: Line 49:
  
 A Fiber would be represented as class which would be defined in core PHP with the following signature: A Fiber would be represented as class which would be defined in core PHP with the following signature:
 +
 +<blockquote>Fiber::this() has been renamed to Fiber::getCurrent() during the PHP 8.1 alpha release phase.</blockquote>
  
 <code php> <code php>
Line 220: Line 224:
 === Fiber Stacks === === Fiber Stacks ===
  
-Each fiber is allocated a separate C stack and VM stack on the heap. The C stack is allocated using ''mmap'' if available, meaning physical memory is used only on demand (if it needs to be allocated to a stack value) on most platforms. Each fiber stack is allocated a maximum of 8M if memory by default, settable with an ini setting ''fiber.stack_size''. Note that this memory is used for the C stack and is not related to the memory available to PHP code. VM stacks for each fiber are allocated in a similar way to generators and use a similar amount of memory and CPU. VM stacks are able to grow dynamically, so only a single VM page (4K) is initially allocated.+Each fiber is allocated a separate C stack and VM stack on the heap. The C stack is allocated using ''mmap'' if available, meaning physical memory is used only on demand (if it needs to be allocated to a stack value) on most platforms. Each fiber stack is allocated a maximum of 8M of memory by default, settable with an ini setting ''fiber.stack_size''. Note that this memory is used for the C stack and is not related to the memory available to PHP code. VM stacks for each fiber are allocated in a similar way to generators and use a similar amount of memory and CPU. VM stacks are able to grow dynamically, so only a single VM page (4K) is initially allocated.
  
 ===== Backward Incompatible Changes ===== ===== Backward Incompatible Changes =====
  
 Declares ''Fiber'', ''FiberError'', ''FiberExit'', and ''ReflectionFiber'' in the root namespace. No other BC breaks. Declares ''Fiber'', ''FiberError'', ''FiberExit'', and ''ReflectionFiber'' in the root namespace. No other BC breaks.
- 
-===== Proposed PHP Version(s) ===== 
- 
-PHP 8.1 
  
 ===== Future Scope ===== ===== Future Scope =====
  
-=== suspend keyword ===+The current implementation does not provide an internal API for fibers for PHP extensions. This RFC focuses on the user space fiber API. An internal fiber API will be added, collaborating with other internal developers and using feedback from PHP extension developers, including Swoole, so fibers can be created and controlled from PHP extensions. An extension may still optionally provide their own custom fiber implementation, but an internal API would allow the extension to use the fiber implementation provided by PHP.
  
-''Fiber::suspend()'' could be replaced with a keyword ''suspend'' that would be similar to ''yield''. The keyword statement would accept an optional expression that would be the suspend value and return the value used to resume the fiber.+===== Proposed PHP Version(s=====
  
-//variable// **= suspend** //expression//**;**+PHP 8.1
  
 ===== Proposed Voting Choices ===== ===== Proposed Voting Choices =====
Line 566: Line 566:
 It is the opinion of the authors of this RFC that it is best to provide the bare minimum in core and allow user code to implement other components as they desire. If the community moves toward a single event loop API or a need emerges for an event loop in PHP core, this can be done in a future RFC. Providing a core event loop without core functionality using it (such as streams, file access, etc.) would be misleading and confusing for users. Deferring such functionality to user frameworks and providing only a minimum API in core keeps expectations in check. It is the opinion of the authors of this RFC that it is best to provide the bare minimum in core and allow user code to implement other components as they desire. If the community moves toward a single event loop API or a need emerges for an event loop in PHP core, this can be done in a future RFC. Providing a core event loop without core functionality using it (such as streams, file access, etc.) would be misleading and confusing for users. Deferring such functionality to user frameworks and providing only a minimum API in core keeps expectations in check.
  
-This RFC does not preclude adding async/await and an event loop to core, see [[#future_scope|Future Scope]].+This RFC does not preclude adding async/await and an event loop to core.
  
 === How does this proposal differ from prior Fiber proposals? === === How does this proposal differ from prior Fiber proposals? ===
Line 583: Line 583:
  
 As noted in [[#why_add_this_to_php_core|“Why add this to PHP core?”]], extensions that profile code, create backtraces, provide execution times, etc. will need to be updated to account for switching between fibers to provide correct data. As noted in [[#why_add_this_to_php_core|“Why add this to PHP core?”]], extensions that profile code, create backtraces, provide execution times, etc. will need to be updated to account for switching between fibers to provide correct data.
 +
 +===== Vote =====
 +
 +Voting started on 2021-03-08 and will run through 2021-03-22. 2/3 required to accept.
 +
 +<doodle title="Add Fibers to PHP?" auth="trowski" voteType="single" closed="true">
 +   * Yes
 +   * No
 +</doodle>
  
 ===== References ===== ===== References =====
rfc/fibers.1615223338.txt.gz · Last modified: 2021/03/08 17:08 by trowski