diff --git a/pyperformance/data-files/benchmarks/MANIFEST b/pyperformance/data-files/benchmarks/MANIFEST index 32089d93..923f261b 100644 --- a/pyperformance/data-files/benchmarks/MANIFEST +++ b/pyperformance/data-files/benchmarks/MANIFEST @@ -2,6 +2,8 @@ name metafile 2to3 +argparse +argparse_subparsers async_generators async_tree async_tree_cpu_io_mixed diff --git a/pyperformance/data-files/benchmarks/bm_argparse/bm_argparse_subparsers.toml b/pyperformance/data-files/benchmarks/bm_argparse/bm_argparse_subparsers.toml new file mode 100644 index 00000000..38044444 --- /dev/null +++ b/pyperformance/data-files/benchmarks/bm_argparse/bm_argparse_subparsers.toml @@ -0,0 +1,10 @@ +[project] +name = "pyperformance_bm_argparse" +requires-python = ">=3.8" +dependencies = ["pyperf"] +urls = {repository = "https://github.com/python/pyperformance"} +dynamic = ["version"] + +[tool.pyperformance] +name = "argparse_subparsers" +extra_opts = ["subparsers"] diff --git a/pyperformance/data-files/benchmarks/bm_argparse/pyproject.toml b/pyperformance/data-files/benchmarks/bm_argparse/pyproject.toml new file mode 100644 index 00000000..0e1040ef --- /dev/null +++ b/pyperformance/data-files/benchmarks/bm_argparse/pyproject.toml @@ -0,0 +1,10 @@ +[project] +name = "pyperformance_bm_argparse" +requires-python = ">=3.8" +dependencies = ["pyperf"] +urls = {repository = "https://github.com/python/pyperformance"} +dynamic = ["version"] + +[tool.pyperformance] +name = "argparse_many_optionals" +extra_opts = ["many_optionals"] diff --git a/pyperformance/data-files/benchmarks/bm_argparse/run_benchmark.py b/pyperformance/data-files/benchmarks/bm_argparse/run_benchmark.py new file mode 100644 index 00000000..edab780e --- /dev/null +++ b/pyperformance/data-files/benchmarks/bm_argparse/run_benchmark.py @@ -0,0 +1,125 @@ +""" +Benchmark argparse programs with: +1) multiple subparsers, each with their own subcommands, and then parse a series of command-line arguments. +2) a large number of optional arguments, and then parse a series of command-line arguments. + +Author: Savannah Ostrowski +""" + +import argparse +import pyperf + + +def generate_arguments(i: int) -> list: + arguments = ["input.txt", "output.txt"] + for i in range(i): + arguments.extend([f"--option{i}", f"value{i}"]) + return arguments + + +def bm_many_optionals() -> argparse.ArgumentParser: + parser = argparse.ArgumentParser(description="A version control system CLI") + + parser.add_argument("--version", action="version", version="1.0") + + subparsers = parser.add_subparsers(dest="command", required=True) + + add_parser = subparsers.add_parser("add", help="Add a file to the repository") + add_parser.add_argument("files", nargs="+", help="List of files to add to staging") + + commit_parser = subparsers.add_parser( + "commit", help="Commit changes to the repository" + ) + commit_parser.add_argument("-m", "--message", required=True, help="Commit message") + + commit_group = commit_parser.add_mutually_exclusive_group(required=False) + commit_group.add_argument( + "--amend", action="store_true", help="Amend the last commit" + ) + commit_group.add_argument( + "--no-edit", action="store_true", help="Reuse the last commit message" + ) + + push_parser = subparsers.add_parser( + "push", help="Push changes to remote repository" + ) + + network_group = push_parser.add_argument_group("Network options") + network_group.add_argument("--dryrun", action="store_true", help="Simulate changes") + network_group.add_argument( + "--timeout", type=int, default=30, help="Timeout in seconds" + ) + + auth_group = push_parser.add_argument_group("Authentication options") + auth_group.add_argument( + "--username", required=True, help="Username for authentication" + ) + auth_group.add_argument( + "--password", required=True, help="Password for authentication" + ) + + global_group = parser.add_mutually_exclusive_group() + global_group.add_argument("--verbose", action="store_true", help="Verbose output") + global_group.add_argument("--quiet", action="store_true", help="Quiet output") + + argument_lists = [ + ["--verbose", "add", "file1.txt", "file2.txt"], + ["add", "file1.txt", "file2.txt"], + ["commit", "-m", "Initial commit"], + ["commit", "-m", "Add new feature", "--amend"], + [ + "push", + "--dryrun", + "--timeout", + "60", + "--username", + "user", + "--password", + "pass", + ], + ] + + for arguments in argument_lists: + parser.parse_args(arguments) + + +def bm_subparsers() -> argparse.ArgumentParser: + parser = argparse.ArgumentParser() + + parser.add_argument("input_file", type=str, help="The input file") + parser.add_argument("output_file", type=str, help="The output file") + + for i in range(1000): + parser.add_argument(f"--option{i}", type=str, help=f"Optional argument {i}") + + argument_lists = [ + generate_arguments(500), + generate_arguments(1000), + ] + + for args in argument_lists: + parser.parse_args(args) + + +BENCHMARKS = { + "many_optionals": bm_many_optionals, + "subparsers": bm_subparsers, +} + + +def add_cmdline_args(cmd, args): + cmd.append(args.benchmark) + + +def add_parser_args(parser): + parser.add_argument("benchmark", choices=BENCHMARKS, help="Which benchmark to run.") + + +if __name__ == "__main__": + runner = pyperf.Runner(add_cmdline_args=add_cmdline_args) + runner.metadata["description"] = "Argparse benchmark" + add_parser_args(runner.argparser) + args = runner.parse_args() + benchmark = args.benchmark + + runner.bench_func(args.benchmark, BENCHMARKS[args.benchmark])