Problem
GeneratedProcessedOption.resetField() is called during clearOptions() before each parse cycle. It resets field values on the command object via the generated accessor. However, for commands that are created fresh for each invocation (the typical CLI single-shot pattern), clearOptions() is redundant -- the fields already have their default/initial values from construction.
In the jbang-like benchmark, every iteration creates a new JBangCommand instance, so all fields are already at their initial values when clearOptions() runs.
Profile Evidence
async-profiler CPU profiling of the jbang-like benchmark (generated path, full startup):
GeneratedProcessedOption.resetField: 1.5% of full CPU (59 samples) -- the 2nd highest aesh frame
ProcessedCommand.clearOptions: 0.4% of full CPU (17 samples)
- Combined: ~2% of full startup CPU spent resetting fields that are already clean
Proposed Fix
Add a clean flag on ProcessedCommand:
- Set to
true after construction (in ProcessedCommandBuilder.create() or ProcessedCommand constructor)
- Cleared to
false after the first parse() / populateObject() call
clearOptions() checks the flag and returns immediately if clean == true
For the interactive REPL case where the same command is reused across multiple invocations, clean is false after the first parse, so clearOptions() runs normally.
Impact
Eliminates ~2% of full startup CPU for single-shot CLI tools (the most common aesh usage pattern). Zero risk for the interactive case since the flag correctly tracks whether options have been modified.
Problem
GeneratedProcessedOption.resetField()is called duringclearOptions()before each parse cycle. It resets field values on the command object via the generated accessor. However, for commands that are created fresh for each invocation (the typical CLI single-shot pattern),clearOptions()is redundant -- the fields already have their default/initial values from construction.In the jbang-like benchmark, every iteration creates a new
JBangCommandinstance, so all fields are already at their initial values whenclearOptions()runs.Profile Evidence
async-profiler CPU profiling of the jbang-like benchmark (generated path, full startup):
GeneratedProcessedOption.resetField: 1.5% of full CPU (59 samples) -- the 2nd highest aesh frameProcessedCommand.clearOptions: 0.4% of full CPU (17 samples)Proposed Fix
Add a
cleanflag onProcessedCommand:trueafter construction (inProcessedCommandBuilder.create()orProcessedCommandconstructor)falseafter the firstparse()/populateObject()callclearOptions()checks the flag and returns immediately ifclean == trueFor the interactive REPL case where the same command is reused across multiple invocations,
cleanisfalseafter the first parse, soclearOptions()runs normally.Impact
Eliminates ~2% of full startup CPU for single-shot CLI tools (the most common aesh usage pattern). Zero risk for the interactive case since the flag correctly tracks whether options have been modified.