Re: [RFC] [Discussion] array_str_contains() for PHP 8.7
| From: | سپهر محمودی | Date: | Mon, 31 Aug 2026 15:35:44 +0000 |
| Subject: | Re: [RFC] [Discussion] array_str_contains() for PHP 8.7 | ||
| References: | 1 2 3 4 5 6 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-132404@lists.php.net to get a copy of this message | ||
در تاریخ دوشنبه ۳۱ اوت ۲۰۲۶، ۱۷:۱۶ Kamil Tekiela
<tekiela246@gmail.com>
نوشت:
> On Mon, 31 Aug 2026 at 14:26, سپهر محمودی <sepehrphpr@gmail.com>
> wrote:
> >
> >
> >
> > در تاریخ دوشنبه ۳۱ اوت ۲۰۲۶، ۱۶:۳۲ Bruce Weirdan
> > <weirdan@gmail.com>
> نوشت:
> >>
> >> Hi سپهر
> >>
> >> On Mon, Aug 31, 2026 at 12:21 AM سپهر محمودی
> >> <sepehrphpr@gmail.com>
> wrote:
> >>>
> >>> While
array_filter with a closure can achieve
> >>> this, it introduces
> noticeable overhead in userland due to repeated closure invocations and
> type checks on every element.
> >>
> >>
> >> If this overhead could be reduced, it would improve the performance of
> any built-in function that calls a user-land closure, not limited to the
> array_filter + str_contains combo. Have you considered solving this problem
> instead, at least for closures generated by partial applications of
> built-in functions?
> >>
> >> --
> >> Best regards,
> >> Bruce Weirdan mailto:
> weirdan@gmail.com
> >
> > --------
> >
> > Hi Bruce,
> >
> > Thanks for the reply.
> >
> > You're right that the closure invocation overhead is not specific to
> > array_filter + str_contains — it applies to any builtin that calls a
> > userland callable. However, I see these as complementary rather than
> > mutually exclusive approaches.
> >
> > Optimizing closure invocation for partial applications is a deep change
> > in the engine (VM loop, call frames, possibly JIT/inline caching), and
> > would only benefit closures created from first-class callable syntax.
> > Even then, the userland code would remain more verbose, and the engine
> > would still have to materialize a call frame per element.
> >
> > A dedicated function avoids the call overhead entirely with a few lines
> > of straightforward C, keeps userland code short and readable, and is
> > shippable now rather than being tied to a long-term engine project.
> >
> > That said, I'd be genuinely interested in seeing a proposal for
> > optimizing first-class callable invocation — I think it would benefit
> > array_map/array_filter users broadly. But I don't think it should block
> > a small, pragmatic stdlib addition.
> >
> > Best regards,
> > Sepehr
> >
>
> Hi Sepehr,
>
> In terms of performance, what numbers are we speaking of here?
> First-class callables have already been significantly improved in
> recent versions of PHP. How much difference is there from a dedicated
> function?
>
> I would rather see array_filter with a callable than a dedicated
> function. It's more understandable to me that way. Also, I agree with
> what others said that I don't consider this code pattern to be
> exceptionally popular to warrant a dedicated optimized function in the
> language. I have never found that to be a performance issue in any
> project.
>
> Regards,
> Kamil
>
----------
Hi Kamil,
Thank you for your feedback and valid points!
Regarding performance:
Even with the great improvements to first-class callables and engine call
overhead in recent PHP versions, there are two key architectural
differences here:
1. Short-circuiting vs Allocation: Using array_filter processes the
entire array and allocates a new filtered array in memory, whereas a
dedicated C implementation (array_str_contains / short-circuit loop)
immediately returns true on the first match without extra allocations.
2. Direct C-level loop: Bypassing the VM dispatch loop for each element
gives noticeable gains, especially on larger datasets or hot paths.
I am currently preparing detailed benchmark comparisons across different
dataset sizes (small, medium, large, and early vs late match scenarios) to
include concrete numbers in the RFC draft.
Regarding readability and utility:
Similar to how str_contains() simplified strpos() !== false or how
array_all() / array_any() were introduced to avoid boilerplate, the
motivation here is to provide a clean, self-describing standard utility
that avoids writing manual loops or memory-allocating filter chains.
That being said, collecting diverse community perspectives like yours is
exactly why we're discussing this early, and I'll make sure the performance
data and use cases are clearly demonstrated in the RFC.
Best regards,
Sepehr