Hi everyone,
I would like to open a broader technical discussion regarding the long-term
design philosophy of PHP's standard library, specifically focusing on the
trade-offs between composable higher-order functions and dedicated native
engine functions.
Over recent major versions, modern PHP has embraced functional programming
idioms with first-class callable syntax, arrow functions, and generic
higher-order operations. While this compositional style significantly
enhances code expressiveness and flexibility, it introduces notable
architectural considerations:
-
Performance & Engine Overhead:
When composing generic higher-order utilities (such as array/string
transformers, filters, and mapping operations), what is the acceptable
threshold for closure invocation overhead and VM context switching in
performance-critical paths? In what scenarios do we consider this overhead
significant enough to warrant dedicated, low-level C implementations in the
engine? -
Standard Library Cohesion & API Surface:
PHP has traditionally provided rich, specialized functions for common data
manipulation tasks. How do we balance keeping the standard library lean and
orthogonal versus providing high-utility, specialized native functions that
eliminate recurring boilerplate across userland applications? -
Performance Benchmarking & JIT Optimization:
As the JIT compiler matures, should the engine rely more heavily on JIT
optimizations to inline higher-order functional patterns, or will
specialized native C functions always remain the preferred standard for
mission-critical operations? -
Edge Cases, Type Consistency & Encodings:
When designing or evolving standard functions across different data domains
(strings, arrays, multibyte handling, streams), what architectural
guidelines should we establish to ensure uniform behavior, strict typing
semantics, and consistent error handling across the entire API surface?
I believe discussing these fundamental trade-offs will help provide clearer
guidelines for future RFC proposals and the continuous evolution of PHP's
standard library.
I look forward to hearing your perspectives and insights.
Best regards,
Sepehr
Hi Sepehr,
I believe discussing these fundamental trade-offs will help provide clearer guidelines for future RFC proposals and the continuous evolution of PHP's standard library.
What are you trying to accomplish with this discussion? What is the
goal? I am asking because I don't quite understand your questions, and
this whole topic seems very vague. What are these clearer guidelines?
Over recent major versions, modern PHP has embraced functional programming idioms with first-class callable syntax, arrow functions, and generic higher-order operations. While this compositional style significantly enhances code expressiveness and flexibility, it introduces notable architectural considerations:
I would never consider first-class callables or arrow functions to be
functional programming idioms. Sure, higher-order functions are
heavily used in functional programming, but they are just as useful in
object-oriented programming or procedural programming.
- Performance & Engine Overhead:
When composing generic higher-order utilities (such as array/string transformers, filters, and mapping operations), what is the acceptable threshold for closure invocation overhead and VM context switching in performance-critical paths? In what scenarios do we consider this overhead significant enough to warrant dedicated, low-level C implementations in the engine?
I don't know if that has ever been a major consideration. We consider
performance on a case-by-case basis. Just like with your recent
proposal, we ask for some hard evidence. How often is it causing a
performance bottleneck in real projects? What kind of performance
improvement would be expected if it were a dedicated function? Etc.
PHP has traditionally provided rich, specialized functions for common data manipulation tasks. How do we balance keeping the standard library lean and orthogonal versus providing high-utility, specialized native functions that eliminate recurring boilerplate across userland applications?
PHP has never been known as a good example in this regard. The
standard library is a complete mess (everything but a kitchen sink).
In recent years, the consensus has been that we only add functions
that provide behaviour which is either impossible or very difficult to
emulate in userland, or so ubiquitous that it deserves a dedicated
function. For example, str_contains was added to simplify strpos !== false, array_first was added to simplify
$array[array_key_first($array)], array_is_list was added to expose
functionality which was quite difficult to emulate in userland. All of
these are examples of very common patterns that were used verbatim
sometimes hundreds of times in a single project.
- Performance Benchmarking & JIT Optimization:
As the JIT compiler matures, should the engine rely more heavily on JIT optimizations to inline higher-order functional patterns, or will specialized native C functions always remain the preferred standard for mission-critical operations?
JIT is only useful for highly specialised applications. For most
applications, such as websites, JIT doesn't offer a lot of benefits.
But besides that, I don't really understand this question. It seems
like a non-sequitur to me.
I won't even attempt to answer the last question, as it seems so vague
to me; one could write a whole book about it and still have more to
add.
Regards,
Kamil
در تاریخ شنبه ۱۲ سپتامبر ۲۰۲۶، ۰۳:۱۹ Kamil Tekiela tekiela246@gmail.com
نوشت:
Hi Sepehr,
I believe discussing these fundamental trade-offs will help provide
clearer guidelines for future RFC proposals and the continuous evolution of
PHP's standard library.What are you trying to accomplish with this discussion? What is the
goal? I am asking because I don't quite understand your questions, and
this whole topic seems very vague. What are these clearer guidelines?Over recent major versions, modern PHP has embraced functional
programming idioms with first-class callable syntax, arrow functions, and
generic higher-order operations. While this compositional style
significantly enhances code expressiveness and flexibility, it introduces
notable architectural considerations:I would never consider first-class callables or arrow functions to be
functional programming idioms. Sure, higher-order functions are
heavily used in functional programming, but they are just as useful in
object-oriented programming or procedural programming.
- Performance & Engine Overhead:
When composing generic higher-order utilities (such as array/string
transformers, filters, and mapping operations), what is the acceptable
threshold for closure invocation overhead and VM context switching in
performance-critical paths? In what scenarios do we consider this overhead
significant enough to warrant dedicated, low-level C implementations in the
engine?I don't know if that has ever been a major consideration. We consider
performance on a case-by-case basis. Just like with your recent
proposal, we ask for some hard evidence. How often is it causing a
performance bottleneck in real projects? What kind of performance
improvement would be expected if it were a dedicated function? Etc.PHP has traditionally provided rich, specialized functions for common
data manipulation tasks. How do we balance keeping the standard library
lean and orthogonal versus providing high-utility, specialized native
functions that eliminate recurring boilerplate across userland applications?PHP has never been known as a good example in this regard. The
standard library is a complete mess (everything but a kitchen sink).
In recent years, the consensus has been that we only add functions
that provide behaviour which is either impossible or very difficult to
emulate in userland, or so ubiquitous that it deserves a dedicated
function. For example,str_containswas added to simplifystrpos !== false,array_firstwas added to simplify
$array[array_key_first($array)],array_is_listwas added to expose
functionality which was quite difficult to emulate in userland. All of
these are examples of very common patterns that were used verbatim
sometimes hundreds of times in a single project.
- Performance Benchmarking & JIT Optimization:
As the JIT compiler matures, should the engine rely more heavily on JIT
optimizations to inline higher-order functional patterns, or will
specialized native C functions always remain the preferred standard for
mission-critical operations?JIT is only useful for highly specialised applications. For most
applications, such as websites, JIT doesn't offer a lot of benefits.
But besides that, I don't really understand this question. It seems
like a non-sequitur to me.I won't even attempt to answer the last question, as it seems so vague
to me; one could write a whole book about it and still have more to
add.Regards,
Kamil
Hi Kamil,
Thank you for the direct feedback. I appreciate you pointing out the
vagueness in my initial questions; that was not my intention, but I see now
that I was approaching the topic from too high an abstraction level.
To clarify my goal: I am not looking for a philosophical treatise, but
rather to understand the practical "threshold" the core team uses when
deciding whether a common pattern (like string searching within an array)
should be implemented as a specialized native function versus leaving it to
userland composition (like array_filter with a closure).
You mentioned that performance is considered on a case-by-case basis with
hard evidence. That is exactly where I want to focus.
Instead of discussing generalities, I will prepare a concrete benchmark. I
plan to compare:
- The overhead of common compositional patterns (e.g., array_filter +
str_contains inside a closure). - The performance of a potential specialized native implementation (e.g.,
a hypothetical array_str_contains).
My goal is to provide the "hard evidence" you mentioned, showing
specifically where the overhead of closure invocation and VM context
switching becomes a measurable bottleneck in common real-world scenarios.
I will follow up with the results once the benchmarking is complete.
Regards,
Sepehr