From f838453bf82add5a5dffb0991d6a07fd7cd1a4a0 Mon Sep 17 00:00:00 2001 From: Weilin Du Date: Fri, 11 Sep 2026 17:40:58 +0800 Subject: [PATCH 1/2] ext/standard: Optimize str_pad() using doubling copies --- UPGRADING | 1 + ext/standard/string.c | 12 ++++---- .../strings/str_pad_repeated_pattern.phpt | 29 +++++++++++++++++++ 3 files changed, 37 insertions(+), 5 deletions(-) create mode 100644 ext/standard/tests/strings/str_pad_repeated_pattern.phpt diff --git a/UPGRADING b/UPGRADING index 5a5cafc0234f..292ad5fba106 100644 --- a/UPGRADING +++ b/UPGRADING @@ -983,6 +983,7 @@ PHP 8.6 UPGRADE NOTES . Improved performance of array_walk(). . Improved performance of intval('+0b...', 2) and intval('0b...', 2). . Improved performance of str_split(). + . Improved performance of str_pad(). - URI: . Improved performance of Uri\WhatWg\Url::parse() when collecting diff --git a/ext/standard/string.c b/ext/standard/string.c index af3f6a461dcf..0264ff5afee4 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -5835,13 +5835,15 @@ static void php_str_pad_fill(zend_string *result, size_t pad_chars, const char * return; } + const char *start = p; const char *end = p + pad_chars; - while (p + pad_str_len <= end) { - p = zend_mempcpy(p, pad_str, pad_str_len); - } + size_t len = MIN(pad_str_len, pad_chars); + p = zend_mempcpy(p, pad_str, len); - if (p < end) { - memcpy(p, pad_str, end - p); + /* Double the filled area on each iteration. */ + while (p < end) { + len = MIN(p - start, end - p); + p = zend_mempcpy(p, start, len); } ZSTR_LEN(result) += pad_chars; diff --git a/ext/standard/tests/strings/str_pad_repeated_pattern.phpt b/ext/standard/tests/strings/str_pad_repeated_pattern.phpt new file mode 100644 index 000000000000..6eebf6d85820 --- /dev/null +++ b/ext/standard/tests/strings/str_pad_repeated_pattern.phpt @@ -0,0 +1,29 @@ +--TEST-- +str_pad() with repeated padding patterns and partial final copies +--FILE-- + $full . $input, + STR_PAD_RIGHT => $input . $full, + STR_PAD_BOTH => substr($repeated, 0, $left) . $input + . substr($repeated, 0, $extra - $left), + ]; + foreach ($expected as $type => $value) { + if (str_pad($input, strlen($input) + $extra, $padding, $type) !== $value) { + throw new Exception("Incorrect padding: type=$type, extra=$extra"); + } + } + } + } +} +echo "Done\n"; +?> +--EXPECT-- +Done From 7018c8c4d633ba50f58376605140dc1db76bda73 Mon Sep 17 00:00:00 2001 From: Weilin Du Date: Fri, 11 Sep 2026 17:46:54 +0800 Subject: [PATCH 2/2] Remove test --- .../strings/str_pad_repeated_pattern.phpt | 29 ------------------- 1 file changed, 29 deletions(-) delete mode 100644 ext/standard/tests/strings/str_pad_repeated_pattern.phpt diff --git a/ext/standard/tests/strings/str_pad_repeated_pattern.phpt b/ext/standard/tests/strings/str_pad_repeated_pattern.phpt deleted file mode 100644 index 6eebf6d85820..000000000000 --- a/ext/standard/tests/strings/str_pad_repeated_pattern.phpt +++ /dev/null @@ -1,29 +0,0 @@ ---TEST-- -str_pad() with repeated padding patterns and partial final copies ---FILE-- - $full . $input, - STR_PAD_RIGHT => $input . $full, - STR_PAD_BOTH => substr($repeated, 0, $left) . $input - . substr($repeated, 0, $extra - $left), - ]; - foreach ($expected as $type => $value) { - if (str_pad($input, strlen($input) + $extra, $padding, $type) !== $value) { - throw new Exception("Incorrect padding: type=$type, extra=$extra"); - } - } - } - } -} -echo "Done\n"; -?> ---EXPECT-- -Done