[php-src] PR #23886: PHP array_splice(): Presize the result when nothing is removed

From: Date: Thu, 24 Sep 2026 12:33:58 +0000
Subject: [php-src] PR #23886: PHP array_splice(): Presize the result when nothing is removed
Groups: php.git-pulls 
Request: Send a blank email to git-pulls+get-38772@lists.php.net to get a copy of this message
Pull Request: https://github.com/php/php-src/pull/23886 Author: mehmetcansahin This PR speeds up array_splice() when inserting without removing elements by allocating enough space upfront, avoiding repeated growth. Behavior is unchanged. Inserting one element in the middle of an array on Apple M1 (release build), using the median of seven runs per build: | input | base | this PR | speedup | |---|---:|---:|---:| | packed, n=16 | 99.8 ns | 77.7 ns | 1.28× | | packed, n=100,000 | 421 µs | 401 µs | within noise¹ | | string keys, n=1,000 | 7.70 µs | 5.82 µs | 1.32× | | string keys, n=100,000 | 1.74 ms | 1.05 ms | 1.66× | ¹ Across the seven runs, base ranged 413–427 µs and this PR 391–429 µs. Inserting one element into an array with 100,000 string keys drops extra peak memory from 7.5 MiB to 5.0 MiB. <details> <summary>Benchmark scripts and methodology</summary> Builds were benchmarked alternately. Each script run reports the lowest average time per iteration across five batches, including the array_pop()/unset() that keeps the array size constant. Timing: ```php <?php function bench(string $label, array $a, int $reps): void { $packed = array_is_list($a); $mid = intdiv(count($a), 2); $best = PHP_FLOAT_MAX; for ($run = 0; $run < 5; $run++) { $t = hrtime(true); for ($r = 0; $r < $reps; $r++) { array_splice($a, $mid, 0, [-1]); if ($packed) { array_pop($a); } else { unset($a[0]); } } $best = min($best, (hrtime(true) - $t) / $reps); } printf("%-24s %10.1f ns/op\n", $label, $best); } $keys = fn(int $n) => array_combine( array_map(fn($i) => "k$i", range(0, $n - 1)), range(0, $n - 1) ); bench('packed n=16', range(0, 15), 1000000); bench('packed n=100,000', range(0, 99999), 1000); bench('string keys n=1,000', $keys(1000), 50000); bench('string keys n=100,000', $keys(100000), 300); ``` Extra peak memory, measured relative to usage before the call: ```php <?php $a = array_combine( array_map(fn($i) => "k$i", range(0, 99999)), range(0, 99999) ); $before = memory_get_usage(); memory_reset_peak_usage(); array_splice($a, 50000, 0, [-1]); printf( "extra peak: %.1f MiB\n", (memory_get_peak_usage() - $before) / 1048576 ); ``` </details>

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