Opened 6 weeks ago
Last modified 7 days ago
#58206 assigned enhancement
Replace usage of strpos with str_contains
Reported by: |
|
Owned by: |
|
---|---|---|---|
Milestone: | 6.3 | Priority: | normal |
Severity: | normal | Version: | |
Component: | General | Keywords: | good-first-bug has-patch 2nd-opinion commit |
Focuses: | performance, coding-standards | Cc: |
Description (last modified by )
Replace usage of false === strpos
or false !== strpos
with str_contains
. It makes the code more readable and use a PHP native function ( which may have a performance benefit ).
Follow on from #58012.
Change History (18)
#2
follow-up:
↓ 3
@
6 weeks ago
str_starts_with
is PHP 8+ syntax, so you cannot just replace strpos
checks with it until the minimum PHP version is raised to PHP 8 if I'm not mistaken...
#3
in reply to:
↑ 2
@
6 weeks ago
- Description modified (diff)
- Milestone changed from Awaiting Review to 6.3
Replying to dingo_d:
str_starts_with
is PHP 8+ syntax, so you cannot just replacestrpos
checks with it until the minimum PHP version is raised to PHP 8 if I'm not mistaken...
WordPress core includes a polyfill for str_contains()
as of [52039] / #49652, as well as str_starts_with()
and str_ends_with()
as of [52040] / #54377, so the change should be safe to make, see the discussion in #58012.
This ticket is about str_contains()
though, updating the description to avoid confusion.
#5
@
6 weeks ago
+1 on these tickets @spacedmonkey!
Patchers: Be careful of loose checks like if ( strpos() )
and if ( ! strpos() )
. These should be evaluated for both str_contains()
and str_starts_with()
(or strpos() > 0
) to maintain backward compatibility and prevent possible security regressions.
This ticket was mentioned in PR #4394 on WordPress/wordpress-develop by @Soean.
6 weeks ago
#6
- Keywords has-patch added
Replace usage of strpos
with str_contains
.
Trac ticket: https://core.trac.wordpress.org/ticket/58206
#7
follow-up:
↓ 8
@
6 weeks ago
I created a pull request for str_contains
, I will create new tickets for str_starts_with
and str_ends_with
.
@spacedmonkey commented on PR #4394:
6 weeks ago
#9
@Soean Good start. I found some more places we could use this function.
6 weeks ago
#10
@spacedmonkey Thanks, I added the post.php line.
In the first step I only changed the strpos( ) === false
and strpos( ) !== false
, as described in the ticket . The others we have to look at very closely, because if a sting starts with a substing strpos
returns 0
which is false
and str_contains
returns true
.
{{{php
$string = '/wp-content'
strpos( $string, '/' ) 0 -> false
str_contains( $string, '/') -> true
}}}
#11
@
5 weeks ago
- Owner set to SergeyBiryukov
- Status changed from new to assigned
@Soean Can you rebase / merge trunk on PR. Core changes have added merge conflicts.
#12
@
5 weeks ago
- Keywords 2nd-opinion changes-requested added
I have "mixed feelings" about this. Imho replacing false === strpos( ... )
and false !== strpos( ... )
with str_contains()
is premature.
The problem is that only ~20% of the current WP sites are on PHP 8+. So 80% will have to use the polyfill. Then the question is: how much slower is the polyfill compared to the native PHP 7.4 code? I did a quick comparison and it seems about 300% slower:
2.350807ms false !== strpos(), 100000 times 7.260107ms str_contains(), 100000 times
So it seems this should be postponed until (at least) more than half of the WP installs are on PHP 8+ as it reduces performance.
#13
follow-up:
↓ 16
@
4 weeks ago
I run benchmarks against this change. I see a net posative.
500 runs of the benchmark - trunk ( 0746cc7324b4b025d1ad3f2afeeb2aadd7d1d19f ) - Theme tt1.
Trunk - PHP 7.4 | PR - PHP 7.4 | Trunk - PHP 8.0 | PR - PHP 8.0 | |
Response Time (median) | 79.64 | 79.6 | 79.4 | 79.31 |
wp-before-template (median) | 32.88 | 32.93 | 32.39 | 32.24 |
wp-template (median) | 40.59 | 40.42 | 40.09 | 40.59 |
wp-total (median) | 73.72 | 73.37 | 72.57 | 72.77 |
There is not a notable improvement performance. As a code quality improvement, this is +1 from me. There are lots of parts of core that use str_contains. For consistency we should use it everywhere.
#16
in reply to:
↑ 13
@
7 days ago
Replying to spacedmonkey:
I run benchmarks against this change. I see a net posative.
Hmmmm, that's really strange? Why would the benchmark you're using miss the 300% slow-down of the PHP < 8 native code vs. the polyfill, and the PHP 8+ native code? Seems something's not right?
#17
@
7 days ago
Maybe the performance lead, @flixos90 could take a look into this.
To be clear, if they’re a slight performance loss, I think this change is worth for the code quality improvement.
Worth noting, the performance team is currently working on docs on how we run our benchmarks. That way we could run the same benchmarks and we could see similar results.
Pinging @SergeyBiryukov