From 558ef4962dd3adb9e63b4c0787f8d4902fc909d4 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 7 Aug 2025 00:00:03 +0200 Subject: [PATCH] hush: optimization: do not glob words "[" and "[[" function old new delta glob_needed 71 86 +15 Signed-off-by: Denys Vlasenko --- shell/hush.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/shell/hush.c b/shell/hush.c index 09ab6ebc0..6129a087b 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -115,6 +115,11 @@ //config:# It's only needed to get "nice" menuconfig indenting. //config:if SHELL_HUSH || HUSH || SH_IS_HUSH || BASH_IS_HUSH //config: +//config:config HUSH_NEED_FOR_SPEED +//config: bool "Faster, but larger code" +//config: default y +//config: depends on SHELL_HUSH +//config: //config:config HUSH_BASH_COMPAT //config: bool "bash-compatible extensions" //config: default y @@ -3381,6 +3386,24 @@ static int o_get_last_ptr(o_string *o, int n) /* Helper */ static int glob_needed(const char *s) { +# if ENABLE_HUSH_NEED_FOR_SPEED + char c = *s; + if (c == '[' /*|| c == '{'*/) { + /* Special-case words consisting entirely of [. + * Optimization to avoid glob() + * on "[ COND ]" and "[[ COND ]]": + * strace hush -c 'i=0; while [ $((++i)) != 50000 ]; do :; done' + * shouldn't be doing 50000 stat("["). + * (Can do it for "{" too, but it's not a common case). + */ + const char *p = s; + while (*++p == c) + continue; + if (*p == '\0') + return 0; + } +# endif + while (*s) { if (*s == '\\') { if (!s[1]) @@ -3572,6 +3595,23 @@ static int perform_glob(o_string *o, int n) /* Helper */ static int glob_needed(const char *s) { +# if ENABLE_HUSH_NEED_FOR_SPEED + char c = *s; + if (c == '[') { + /* Special-case words consisting entirely of [. + * Optimization to avoid glob() + * on "[ COND ]" and "[[ COND ]]": + * strace hush -c 'i=0; while [ $((++i)) != 50000 ]; do :; done' + * shouldn't be doing 50000 stat("["). + */ + const char *p = s; + while (*++p == c) + continue; + if (*p == '\0') + return 0; + } +# endif + while (*s) { if (*s == '\\') { if (!s[1])