Commit ae62043aa34 for php.net
commit ae62043aa340871abfeea8568565d23d8b42f35a
Author: Weilin Du <weilindu@php.net>
Date: Sun Sep 13 00:04:17 2026 +0800
ext/mbstring: Optimize mb_str_pad() using doubling copies (#23667)
Follow-up #23661. Use the same optimization on mb_str_pad.
Co-authored-by: David CARLIER <devnexen@gmail.com>
diff --git a/UPGRADING b/UPGRADING
index 3980faa4294..7c7b727759b 100644
--- a/UPGRADING
+++ b/UPGRADING
@@ -1091,6 +1091,9 @@ PHP 8.6 UPGRADE NOTES
. Improved performance of transliterator_list_ids() and
resourcebundle_locales() by pre-allocating their returned arrays.
+- Mbstring:
+ . Improved performance of mb_str_pad().
+
- Phar:
. Reduced temporary allocations when iterating Phar directories.
diff --git a/ext/mbstring/mbstring.c b/ext/mbstring/mbstring.c
index ed3e8bd1cf4..c701a23183b 100644
--- a/ext/mbstring/mbstring.c
+++ b/ext/mbstring/mbstring.c
@@ -5906,6 +5906,28 @@ PHP_FUNCTION(mb_chr)
}
/* }}} */
+static char *php_mb_str_pad_fill(char *buffer, const zend_string *pad, size_t pad_bytes)
+{
+ if (pad_bytes == 0) {
+ return buffer;
+ }
+ if (ZSTR_LEN(pad) == 1) {
+ memset(buffer, ZSTR_VAL(pad)[0], pad_bytes);
+ return buffer + pad_bytes;
+ }
+
+ const char *start = buffer;
+ const char *end = buffer + pad_bytes;
+ buffer = zend_mempcpy(buffer, ZSTR_VAL(pad), ZSTR_LEN(pad));
+
+ /* Double the filled area on each iteration. */
+ while (buffer < end) {
+ size_t len = MIN(buffer - start, end - buffer);
+ buffer = zend_mempcpy(buffer, start, len);
+ }
+ return buffer;
+}
+
PHP_FUNCTION(mb_str_pad)
{
zend_string *input, *encoding_str = NULL, *pad = ZSTR_CHAR(' ');
@@ -6006,9 +6028,7 @@ PHP_FUNCTION(mb_str_pad)
char *buffer = ZSTR_VAL(result);
/* First we pad the left. */
- for (size_t i = 0; i < full_left_pad_copies; i++, buffer += ZSTR_LEN(pad)) {
- memcpy(buffer, ZSTR_VAL(pad), ZSTR_LEN(pad));
- }
+ buffer = php_mb_str_pad_fill(buffer, pad, full_left_pad_bytes);
memcpy(buffer, ZSTR_VAL(remaining_left_pad_str), ZSTR_LEN(remaining_left_pad_str));
buffer += ZSTR_LEN(remaining_left_pad_str);
@@ -6017,9 +6037,7 @@ PHP_FUNCTION(mb_str_pad)
buffer += ZSTR_LEN(input);
/* Finally, we pad on the right. */
- for (size_t i = 0; i < full_right_pad_copies; i++, buffer += ZSTR_LEN(pad)) {
- memcpy(buffer, ZSTR_VAL(pad), ZSTR_LEN(pad));
- }
+ buffer = php_mb_str_pad_fill(buffer, pad, full_right_pad_bytes);
memcpy(buffer, ZSTR_VAL(remaining_right_pad_str), ZSTR_LEN(remaining_right_pad_str));
ZSTR_VAL(result)[ZSTR_LEN(result)] = '\0';