[php-src] PR #23556: array_chunk(): Fill packed chunks directly when keys are not preserved

From: Date: Thu, 03 Sep 2026 13:28:39 +0000
Subject: [php-src] PR #23556: array_chunk(): Fill packed chunks directly when keys are not preserved
Groups: php.git-pulls 
Request: Send a blank email to git-pulls+get-38282@lists.php.net to get a copy of this message
Pull Request: https://github.com/php/php-src/pull/23556 Author: mehmetcansahin When $preserve_keys is false (the default), every chunk is a list of at most $size elements. array_chunk() now fills each chunk directly using ZEND_HASH_FILL_PACKED instead of calling zend_hash_next_index_insert() for each element. The input is traversed through its element storage using a stride computed once, allowing packed and mixed arrays to share the same loop. Holes (IS_UNDEF entries) are skipped, and references with a refcount of one are unwrapped as before. The key-preserving insertion logic and behavior remain unchanged. ### Benchmarks array_chunk($input, $size, false) on an Apple M1 using a release build (best of three runs). Base commit: ec93b0b941dc. | input | size | repetitions | base | this PR | speedup | |---|---:|---:|---:|---:|---:| | packed, n=100 | 10 | 200,000 | 144.5 ms | 69.7 ms | 2.1× | | packed, n=1,000 | 10 | 20,000 | 139.9 ms | 64.0 ms | 2.2× | | packed, n=1,000 | 100 | 20,000 | 105.3 ms | 38.5 ms | 2.7× | | packed, n=100,000 | 100 | 200 | 110.7 ms | 38.9 ms | 2.8× | | string keys, n=1,000 | 10 | 20,000 | 140.0 ms | 64.1 ms | 2.2× | Control check with $preserve_keys = true (packed input, n = 1,000, $size = 10, 20,000 repetitions): 189.3 ms → 181.3 ms; no regression observed. <details> <summary>Benchmark script</summary> ```php <?php function bench(string $label, array $input, int $size, bool $preserve, int $reps): void { $best = PHP_FLOAT_MAX; for ($run = 0; $run < 3; $run++) { $t = hrtime(true); for ($r = 0; $r < $reps; $r++) { array_chunk($input, $size, $preserve); } $best = min($best, (hrtime(true) - $t) / 1e6); } printf("%-28s size=%-5d x%-7d best: %8.1f ms\n", $label, $size, $reps, $best); } $hash = []; for ($i = 0; $i < 1000; $i++) { $hash["k$i"] = $i; } bench('packed n=100', range(0, 99), 10, false, 200000); bench('packed n=1000', range(0, 999), 10, false, 20000); bench('packed n=1000', range(0, 999), 100, false, 20000); bench('packed n=100000', range(0, 99999), 100, false, 200); bench('string keys n=1000', $hash, 10, false, 20000); bench('packed n=1000 preserve', range(0, 999), 10, true, 20000); ``` </details>

« previous php.git-pulls (#38282) next »