Skip to content

Conversation

@ndossche
Copy link
Member

@ndossche ndossche commented Nov 7, 2025

Three optimizations:

  • If the entire string is returned, we don't need to duplicate it.
  • Use packed filling logic.
  • Use fast construction of strings. This is useful when splitting strings on length=1. In that case I get a 6x speedup in the code below.

Bench:

$x = str_repeat('A', 100);
for ($i = 0; $i < 1000000; $i++)
    str_split($x, 10);

On an i7-4790:

Benchmark 1: ./sapi/cli/php x.php
  Time (mean ± σ):     160.1 ms ±   6.4 ms    [User: 157.3 ms, System: 1.8 ms]
  Range (min … max):   155.6 ms … 184.7 ms    18 runs

Benchmark 2: ./sapi/cli/php_old x.php
  Time (mean ± σ):     202.6 ms ±   4.0 ms    [User: 199.1 ms, System: 1.9 ms]
  Range (min … max):   197.4 ms … 209.2 ms    14 runs

Summary
  ./sapi/cli/php x.php  ran
    1.27 ± 0.06 times faster than ./sapi/cli/php_old x.php

The performance gain increases with smaller lengths.

@ndossche
Copy link
Member Author

ndossche commented Nov 7, 2025

Interestingly -0.17% Icount on symfony demo, wonder how much this is noisy / real.

@ndossche ndossche marked this pull request as ready for review November 7, 2025 22:17
@ndossche ndossche requested a review from bukka as a code owner November 7, 2025 22:17
add_next_index_stringl(return_value, p, split_length);
p += split_length;
}
ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can this also be applied to the multibyte version?

PHP_FUNCTION(mb_str_split)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but it may be a bit more difficult.

Copy link
Member

@arnaud-lb arnaud-lb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks right!

Three optimizations:
- If the entire string is returned, we don't need to duplicate it.
- Use packed filling logic.
- Use fast construction of strings. This is useful when splitting
  strings on length=1. In that case I get a 6x speedup in the code
  below.

Bench:
```php
$x = str_repeat('A', 100);
for ($i = 0; $i < 1000000; $i++)
    str_split($x, 10);
```

On an i7-4790:
```
Benchmark 1: ./sapi/cli/php x.php
  Time (mean ± σ):     160.1 ms ±   6.4 ms    [User: 157.3 ms, System: 1.8 ms]
  Range (min … max):   155.6 ms … 184.7 ms    18 runs

Benchmark 2: ./sapi/cli/php_old x.php
  Time (mean ± σ):     202.6 ms ±   4.0 ms    [User: 199.1 ms, System: 1.9 ms]
  Range (min … max):   197.4 ms … 209.2 ms    14 runs

Summary
  ./sapi/cli/php x.php  ran
    1.27 ± 0.06 times faster than ./sapi/cli/php_old x.php
```

The performance gain increases with smaller lengths.
@ndossche ndossche merged commit a09cc6e into php:master Nov 8, 2025
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants