Skip to content

Commit ae62043

Browse files
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>
1 parent a7b265c commit ae62043

2 files changed

Lines changed: 27 additions & 6 deletions

File tree

UPGRADING

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1091,6 +1091,9 @@ PHP 8.6 UPGRADE NOTES
10911091
. Improved performance of transliterator_list_ids() and
10921092
resourcebundle_locales() by pre-allocating their returned arrays.
10931093

1094+
- Mbstring:
1095+
. Improved performance of mb_str_pad().
1096+
10941097
- Phar:
10951098
. Reduced temporary allocations when iterating Phar directories.
10961099

ext/mbstring/mbstring.c

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5906,6 +5906,28 @@ PHP_FUNCTION(mb_chr)
59065906
}
59075907
/* }}} */
59085908

5909+
static char *php_mb_str_pad_fill(char *buffer, const zend_string *pad, size_t pad_bytes)
5910+
{
5911+
if (pad_bytes == 0) {
5912+
return buffer;
5913+
}
5914+
if (ZSTR_LEN(pad) == 1) {
5915+
memset(buffer, ZSTR_VAL(pad)[0], pad_bytes);
5916+
return buffer + pad_bytes;
5917+
}
5918+
5919+
const char *start = buffer;
5920+
const char *end = buffer + pad_bytes;
5921+
buffer = zend_mempcpy(buffer, ZSTR_VAL(pad), ZSTR_LEN(pad));
5922+
5923+
/* Double the filled area on each iteration. */
5924+
while (buffer < end) {
5925+
size_t len = MIN(buffer - start, end - buffer);
5926+
buffer = zend_mempcpy(buffer, start, len);
5927+
}
5928+
return buffer;
5929+
}
5930+
59095931
PHP_FUNCTION(mb_str_pad)
59105932
{
59115933
zend_string *input, *encoding_str = NULL, *pad = ZSTR_CHAR(' ');
@@ -6006,9 +6028,7 @@ PHP_FUNCTION(mb_str_pad)
60066028
char *buffer = ZSTR_VAL(result);
60076029

60086030
/* First we pad the left. */
6009-
for (size_t i = 0; i < full_left_pad_copies; i++, buffer += ZSTR_LEN(pad)) {
6010-
memcpy(buffer, ZSTR_VAL(pad), ZSTR_LEN(pad));
6011-
}
6031+
buffer = php_mb_str_pad_fill(buffer, pad, full_left_pad_bytes);
60126032
memcpy(buffer, ZSTR_VAL(remaining_left_pad_str), ZSTR_LEN(remaining_left_pad_str));
60136033
buffer += ZSTR_LEN(remaining_left_pad_str);
60146034

@@ -6017,9 +6037,7 @@ PHP_FUNCTION(mb_str_pad)
60176037
buffer += ZSTR_LEN(input);
60186038

60196039
/* Finally, we pad on the right. */
6020-
for (size_t i = 0; i < full_right_pad_copies; i++, buffer += ZSTR_LEN(pad)) {
6021-
memcpy(buffer, ZSTR_VAL(pad), ZSTR_LEN(pad));
6022-
}
6040+
buffer = php_mb_str_pad_fill(buffer, pad, full_right_pad_bytes);
60236041
memcpy(buffer, ZSTR_VAL(remaining_right_pad_str), ZSTR_LEN(remaining_right_pad_str));
60246042

60256043
ZSTR_VAL(result)[ZSTR_LEN(result)] = '\0';

0 commit comments

Comments
 (0)