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