From 90b9484dcfe84cbb60b073e23a137f8ef92fcf0e Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 25 Nov 2023 15:58:38 +0100 Subject: [PATCH] Fix GH-12778: Windows IIS FastCGI Spin-Up Performance Slowdown The issue isn't limited to Windows only, I can also see the slowdown on my Linux machine. The cause of the slowdown is 26e424465c. In that commit a locale reset routine was implemented that gets called on startup. The fix from that commit is only necessary when using readline functionality, there are three places that is used: - phpdbg - with readline_cli - readline() php function So we make sure we only reset the locale when one of these is used, preventing the overhead on normal website-serving use-cases. --- UPGRADING.INTERNALS | 8 ++++++++ ext/readline/readline.c | 11 +++++++++++ ext/readline/readline_cli.c | 2 ++ main/main.c | 1 - sapi/phpdbg/phpdbg.c | 2 ++ 5 files changed, 23 insertions(+), 1 deletion(-) diff --git a/UPGRADING.INTERNALS b/UPGRADING.INTERNALS index f3c394bf3224c..e224eed6c9e3c 100644 --- a/UPGRADING.INTERNALS +++ b/UPGRADING.INTERNALS @@ -63,3 +63,11 @@ PHP 8.4 INTERNALS UPGRADE NOTES ======================== 5. SAPI changes ======================== + +* The LC_CTYPE locale is no longer overridden at module startup to C.UTF-8. + This was originally introduced to fix an issue with UTF-8 characters when + libedit was used for providing the readline functionality. The new fix now + delays the locale reset until the readline functionality is actually used. + SAPIs relying on this behaviour must manually call zend_reset_lc_ctype_locale(). + This change is done to fix a performance regression. + See https://github.com/php/php-src/pull/12784. diff --git a/ext/readline/readline.c b/ext/readline/readline.c index db2776fb27a9a..385400f642276 100644 --- a/ext/readline/readline.c +++ b/ext/readline/readline.c @@ -115,6 +115,15 @@ PHP_MINFO_FUNCTION(readline) /* }}} */ +static void php_readline_fix_locale() { + /* Yes, this variable is process-wide, but so is the locale setting. */ + static bool locale_fixed = false; + if (!locale_fixed) { + locale_fixed = true; + zend_reset_lc_ctype_locale(); + } +} + /* {{{ Reads a line */ PHP_FUNCTION(readline) { @@ -126,6 +135,8 @@ PHP_FUNCTION(readline) RETURN_THROWS(); } + php_readline_fix_locale(); + result = readline(prompt); if (! result) { diff --git a/ext/readline/readline_cli.c b/ext/readline/readline_cli.c index 4afe7be3f667c..c787d70e5e2eb 100644 --- a/ext/readline/readline_cli.c +++ b/ext/readline/readline_cli.c @@ -634,6 +634,8 @@ static int readline_shell_run(void) /* {{{ */ #endif read_history(history_file); + zend_reset_lc_ctype_locale(); + EG(exit_status) = 0; while ((line = readline(ZSTR_VAL(prompt))) != NULL) { if (strcmp(line, "exit") == 0 || strcmp(line, "quit") == 0) { diff --git a/main/main.c b/main/main.c index fa296eed3074f..5bd12e7762d6c 100644 --- a/main/main.c +++ b/main/main.c @@ -2104,7 +2104,6 @@ zend_result php_module_startup(sapi_module_struct *sf, zend_module_entry *additi zuf.getenv_function = sapi_getenv; zuf.resolve_path_function = php_resolve_path_for_zend; zend_startup(&zuf); - zend_reset_lc_ctype_locale(); zend_update_current_locale(); zend_observer_startup(); diff --git a/sapi/phpdbg/phpdbg.c b/sapi/phpdbg/phpdbg.c index a69ac171cface..93d7a717bc752 100644 --- a/sapi/phpdbg/phpdbg.c +++ b/sapi/phpdbg/phpdbg.c @@ -1356,6 +1356,8 @@ int main(int argc, char **argv) /* {{{ */ PHPDBG_G(flags) = flags; if (phpdbg->startup(phpdbg) == SUCCESS) { + zend_reset_lc_ctype_locale(); + zend_mm_heap *mm_heap; #ifdef _WIN32 EXCEPTION_POINTERS *xp;