Commit 82477067513 for php.net

commit 824770675130360543604e03b9f828a0e41c91ad
Author: Xuyang Zhang <119476662+kn1g78@users.noreply.github.com>
Date:   Sat Jun 27 18:08:38 2026 +0800

    ext/intl: Pre-size arrays created from ICU enumerations (#22483)

    Use uenum_count() to pre-size arrays built from ICU enumerations.

    This avoids unnecessary HashTable growth in transliterator_list_ids(),
    resourcebundle_locales() and locale_get_keywords().

    locale_get_keywords() also uses the keyword length reported by ICU when
    inserting the associative entry, with a fallback to strlen() for unknown
    lengths.

    If counting fails, the previous behavior is preserved by falling back to an
    unsized array initialization.

diff --git a/UPGRADING b/UPGRADING
index 15c1aad15db..0c5253267e3 100644
--- a/UPGRADING
+++ b/UPGRADING
@@ -500,6 +500,10 @@ PHP 8.6 UPGRADE NOTES
   . Improved performance of indentation generation in json_encode()
     when using PHP_JSON_PRETTY_PRINT.

+- Intl:
+  . Improved performance of transliterator_list_ids() and
+    resourcebundle_locales() by pre-allocating their returned arrays.
+
 - Phar:
   . Reduced temporary allocations when iterating Phar directories.

diff --git a/ext/intl/resourcebundle/resourcebundle_class.cpp b/ext/intl/resourcebundle/resourcebundle_class.cpp
index f796a6ffc8a..7e22e9e8c7d 100644
--- a/ext/intl/resourcebundle/resourcebundle_class.cpp
+++ b/ext/intl/resourcebundle/resourcebundle_class.cpp
@@ -339,6 +339,7 @@ U_CFUNC PHP_FUNCTION( resourcebundle_locales )
 	size_t    bundlename_len = 0;
 	const char * entry;
 	int entry_len;
+	int32_t count;
 	UEnumeration *icuenum;
 	UErrorCode   icuerror = U_ZERO_ERROR;

@@ -364,7 +365,13 @@ U_CFUNC PHP_FUNCTION( resourcebundle_locales )
 	uenum_reset( icuenum, &icuerror );
 	INTL_CHECK_STATUS(icuerror, "Cannot iterate locales list");

-	array_init( return_value );
+	count = uenum_count( icuenum, &icuerror );
+	if (U_FAILURE(icuerror)) {
+		count = 0;
+		icuerror = U_ZERO_ERROR;
+	}
+
+	array_init_size( return_value, count );
 	while ((entry = uenum_next( icuenum, &entry_len, &icuerror ))) {
 		add_next_index_stringl( return_value, (char *) entry, entry_len);
 	}
diff --git a/ext/intl/transliterator/transliterator_methods.cpp b/ext/intl/transliterator/transliterator_methods.cpp
index 45dd00b42bc..8efcff95b31 100644
--- a/ext/intl/transliterator/transliterator_methods.cpp
+++ b/ext/intl/transliterator/transliterator_methods.cpp
@@ -21,6 +21,8 @@
 #include <unicode/unistr.h>
 #endif

+#include <unicode/uenum.h>
+
 extern "C" {
 #include "php_intl.h"
 #include "intl_data.h"
@@ -226,6 +228,7 @@ U_CFUNC PHP_FUNCTION( transliterator_list_ids )
 	UEnumeration  *en;
 	const UChar	  *elem;
 	int32_t		  elem_len;
+	int32_t		  count;
 	UErrorCode	  status = U_ZERO_ERROR;

 	intl_error_reset( nullptr );
@@ -236,7 +239,14 @@ U_CFUNC PHP_FUNCTION( transliterator_list_ids )
 	INTL_CHECK_STATUS( status,
 		"Failed to obtain registered transliterators" );

-	array_init( return_value );
+	count = uenum_count( en, &status );
+	if( U_FAILURE( status ) )
+	{
+		count = 0;
+		status = U_ZERO_ERROR;
+	}
+
+	array_init_size( return_value, count );
 	while( (elem = uenum_unext( en, &elem_len, &status )) )
 	{
 		zend_string *el = intl_convert_utf16_to_utf8(elem, elem_len, &status );