I spent some time running the argparse bm_subparsers benchmark from pyperformance (1000 optional arguments, 10 iterations)
| Version |
Time |
Function Calls |
| 3.10 |
0.585s |
560K |
| 3.11 |
0.207s |
560K |
| 3.12 |
0.229s |
560K |
| 3.13 |
0.246s |
560K |
| 3.14 |
0.934s |
2,380K |
| 3.15 (main) |
0.883s |
2,367K |
For a "realistic" CLI with 10 arguments, parser creation is ~3x slower on main compared to 3.13.
The root cause is that _get_formatter() is called twice per add_argument() - once for metavar validation and once in _check_help() for help string validation (called at the end of add_argument ). Each _get_formatter() call creates a new HelpFormatter, which calls _set_color(), which calls can_colorize(), which checks 5 environment variables.
I think a viable fix is to cache the HelpFormatter on ArgumentParser for validation operations. The validation only performs read-only operations (_format_args, _expand_help) that don't modify formatter state. This preserves the existing _get_formatter() behavior while eliminating redundant _set_color() calls during argument setup.
Linked PRs
I spent some time running the argparse
bm_subparsersbenchmark frompyperformance(1000 optional arguments, 10 iterations)For a "realistic" CLI with 10 arguments, parser creation is ~3x slower on main compared to 3.13.
The root cause is that
_get_formatter()is called twice peradd_argument()- once for metavar validation and once in_check_help()for help string validation (called at the end ofadd_argument). Each_get_formatter()call creates a newHelpFormatter, which calls_set_color(), which callscan_colorize(), which checks 5 environment variables.I think a viable fix is to cache the
HelpFormatteronArgumentParserfor validation operations. The validation only performs read-only operations (_format_args,_expand_help) that don't modify formatter state. This preserves the existing_get_formatter()behavior while eliminating redundant_set_color()calls during argument setup.Linked PRs
_set_colorcalls #142268_set_colorcalls (GH-142268) #142313