From: Xiang Gao <[email protected]>

This is an RFC patch for a performance regression observerd in
a customer production workload. The workload used a large number
of exported shell variables and command substitutions. I reduced
it to the following Fedora reproducer:

    for ((i=0;i<10000;i++)); do
        export BATCH_ETL_PORT$i=192.168.100.$i
    done

    time for ((i=0;i<100;i++)); do
        x=$(date +%s%N)
    done

On my Fedora test system, bash-5.0 takes tens of seconds for this test,
while bash-4.4 completes it in about 1 second. If the same 10000 variables
are not exported, bash-5.0 also completes in about 1 seconds. Pure
builtin loops such as `: test` or `echo test` do not show a meaningful
regression.

Perf and temporary instrumentation point to repeated export environment
rebuilds in command-substitution children.

The parent shell has a clean export_env, but each command-substitution
child reaches maybe_make_export_env() with array_needs_making set and
rebuilds about 10000 export_env entries.

The suspected cause is the nofork exec path in execute_cmd.c:
adjust_shell_level(-1) updates exported SHLVL before maybe_make_export_env(),
which marks export_env dirty and forces a full rebuild in each child. This
patch builds export_env first, adjusts SHLVL, then updates SHLVL in
export_env in place.

Please review this as an RFC, especially the SHLVL/export_env semantics and
whether clearing array_needs_making after the in-place SHLVL update is safe.


Xiang Gao (1):
  execute_cmd: avoid rebuilding export environment in comsub exec path

 execute_cmd.c | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

-- 
2.53.0


Reply via email to