@@ -50,6 +50,32 @@ def _run_once(
5050 shutil .rmtree (output_dir , ignore_errors = True )
5151
5252
53+ def _run_size_once (
54+ * ,
55+ generate_client : Any ,
56+ generation_request : Any ,
57+ spec_json : str ,
58+ package_name : str ,
59+ ) -> tuple [dict [str , int ], Any ]:
60+ output_dir = Path (tempfile .mkdtemp (prefix = "openapi-python-size-" ))
61+ try :
62+ result = generate_client (
63+ generation_request (
64+ output_dir = output_dir ,
65+ spec_json = spec_json ,
66+ package_name = package_name ,
67+ overwrite = True ,
68+ )
69+ )
70+ file_sizes = {
71+ path .relative_to (output_dir ).as_posix (): path .stat ().st_size
72+ for path in result .written_files
73+ }
74+ return file_sizes , result
75+ finally :
76+ shutil .rmtree (output_dir , ignore_errors = True )
77+
78+
5379def run_benchmark (args : argparse .Namespace ) -> int :
5480 spec_json = _load_spec (args .spec )
5581 generation_request , generate_client = _load_generator (args .package_path )
@@ -93,6 +119,35 @@ def run_benchmark(args: argparse.Namespace) -> int:
93119 return 0
94120
95121
122+ def run_size_benchmark (args : argparse .Namespace ) -> int :
123+ spec_json = _load_spec (args .spec )
124+ generation_request , generate_client = _load_generator (args .package_path )
125+
126+ file_sizes , result = _run_size_once (
127+ generate_client = generate_client ,
128+ generation_request = generation_request ,
129+ spec_json = spec_json ,
130+ package_name = args .package ,
131+ )
132+
133+ payload = {
134+ "files_bytes" : file_sizes ,
135+ "operations" : result .operations ,
136+ "total_bytes" : sum (file_sizes .values ()),
137+ "type_definitions" : result .type_definitions ,
138+ }
139+
140+ encoded = json .dumps (payload , indent = 2 , sort_keys = True )
141+ if args .output :
142+ args .output .write_text (encoded + "\n " , encoding = "utf-8" )
143+ print (encoded )
144+ return 0
145+
146+
147+ def _format_bytes (value : float ) -> str :
148+ return f"{ value :,.0f} bytes"
149+
150+
96151def compare_benchmarks (args : argparse .Namespace ) -> int :
97152 baseline = json .loads (args .baseline .read_text (encoding = "utf-8" ))
98153 candidate = json .loads (args .candidate .read_text (encoding = "utf-8" ))
@@ -116,6 +171,29 @@ def compare_benchmarks(args: argparse.Namespace) -> int:
116171 return 0
117172
118173
174+ def compare_size_benchmarks (args : argparse .Namespace ) -> int :
175+ baseline = json .loads (args .baseline .read_text (encoding = "utf-8" ))
176+ candidate = json .loads (args .candidate .read_text (encoding = "utf-8" ))
177+
178+ baseline_bytes = float (baseline ["total_bytes" ])
179+ candidate_bytes = float (candidate ["total_bytes" ])
180+ allowed_bytes = baseline_bytes * (1 + args .max_regression )
181+ change = (candidate_bytes - baseline_bytes ) / baseline_bytes
182+
183+ print (f"baseline total: { _format_bytes (baseline_bytes )} " )
184+ print (f"candidate total: { _format_bytes (candidate_bytes )} " )
185+ print (f"change: { change :+.2%} " )
186+ print (f"limit: +{ args .max_regression :.2%} " )
187+
188+ if candidate_bytes > allowed_bytes :
189+ print (
190+ "generated file size regressed beyond the configured limit" ,
191+ file = sys .stderr ,
192+ )
193+ return 1
194+ return 0
195+
196+
119197def _build_parser () -> argparse .ArgumentParser :
120198 parser = argparse .ArgumentParser (
121199 prog = "benchmark_generate.py" ,
@@ -132,12 +210,27 @@ def _build_parser() -> argparse.ArgumentParser:
132210 run .add_argument ("--output" , type = Path )
133211 run .set_defaults (func = run_benchmark )
134212
213+ size = subcommands .add_parser ("size" , help = "Measure generated file sizes" )
214+ size .add_argument ("--spec" , type = Path , required = True )
215+ size .add_argument ("--package-path" , type = Path , default = Path .cwd ())
216+ size .add_argument ("--package" , default = "my_client" )
217+ size .add_argument ("--output" , type = Path )
218+ size .set_defaults (func = run_size_benchmark )
219+
135220 compare = subcommands .add_parser ("compare" , help = "Compare two benchmark results" )
136221 compare .add_argument ("--baseline" , type = Path , required = True )
137222 compare .add_argument ("--candidate" , type = Path , required = True )
138223 compare .add_argument ("--max-regression" , type = float , default = 0.02 )
139224 compare .set_defaults (func = compare_benchmarks )
140225
226+ compare_size = subcommands .add_parser (
227+ "compare-size" , help = "Compare two generated file size results"
228+ )
229+ compare_size .add_argument ("--baseline" , type = Path , required = True )
230+ compare_size .add_argument ("--candidate" , type = Path , required = True )
231+ compare_size .add_argument ("--max-regression" , type = float , default = 0.02 )
232+ compare_size .set_defaults (func = compare_size_benchmarks )
233+
141234 return parser
142235
143236
0 commit comments