@@ -53,8 +53,27 @@ def run_worker(target_module):
5353 "loaded_lines" : loaded_lines
5454 }))
5555
56+ def _run_worker_and_parse (cmd ):
57+ result = subprocess .run (cmd , capture_output = True , text = True , check = True )
58+ try :
59+ lines = result .stdout .strip ().splitlines ()
60+ if not lines :
61+ raise ValueError ("Worker produced no output on stdout." )
62+ data = json .loads (lines [- 1 ])
63+ for key in ("time_ms" , "peak_ram_mb" , "loaded_modules" , "loaded_lines" ):
64+ if key not in data :
65+ raise KeyError (f"Missing key '{ key } ' in worker output" )
66+ return data
67+ except (json .JSONDecodeError , IndexError , KeyError , ValueError ) as parse_err :
68+ print (f"Error parsing worker output: { parse_err } " , file = sys .stderr )
69+ print (f"Worker stdout:\n { result .stdout } " , file = sys .stderr )
70+ print (f"Worker stderr:\n { result .stderr } " , file = sys .stderr )
71+ raise parse_err
72+
5673def run_master (iterations , target_module , cpu = "0" , csv_path = None ):
5774 """Orchestrates the benchmark."""
75+ if iterations < 1 :
76+ raise ValueError ("Number of iterations must be at least 1." )
5877 times , memories = [], []
5978 loaded_modules_val , loaded_lines_val = 0 , 0
6079
@@ -73,27 +92,23 @@ def run_master(iterations, target_module, cpu="0", csv_path=None):
7392 cmd += [sys .executable , __file__ , "--worker" , f"--module={ target_module } " ]
7493
7594 try :
76- result = subprocess .run (
77- cmd , capture_output = True , text = True , check = True
78- )
79- data = json .loads (result .stdout .strip ().splitlines ()[- 1 ])
95+ data = _run_worker_and_parse (cmd )
8096 times .append (data ["time_ms" ])
8197 memories .append (data ["peak_ram_mb" ])
82- loaded_modules_val = data . get ( "loaded_modules" , 0 )
83- loaded_lines_val = data . get ( "loaded_lines" , 0 )
98+ loaded_modules_val = data [ "loaded_modules" ]
99+ loaded_lines_val = data [ "loaded_lines" ]
84100 except (subprocess .CalledProcessError , FileNotFoundError ) as e :
85101 # Fallback if taskset is not found or fails
86102 if cpu .lower () != "none" and i == 0 :
87103 print ("WARNING: taskset CPU pinning failed or is not available. Falling back to unpinned execution..." )
88104 # Try running without taskset
89105 cmd = [sys .executable , __file__ , "--worker" , f"--module={ target_module } " ]
90106 try :
91- result = subprocess .run (cmd , capture_output = True , text = True , check = True )
92- data = json .loads (result .stdout .strip ().splitlines ()[- 1 ])
107+ data = _run_worker_and_parse (cmd )
93108 times .append (data ["time_ms" ])
94109 memories .append (data ["peak_ram_mb" ])
95- loaded_modules_val = data . get ( "loaded_modules" , 0 )
96- loaded_lines_val = data . get ( "loaded_lines" , 0 )
110+ loaded_modules_val = data [ "loaded_modules" ]
111+ loaded_lines_val = data [ "loaded_lines" ]
97112 cpu = "none" # Disable cpu pinning for remaining iterations
98113 except subprocess .CalledProcessError as err :
99114 print (f"Error in worker process:\n { err .stderr } " , file = sys .stderr )
@@ -160,7 +175,13 @@ def run_trace(target_module):
160175 [sys .executable , "-X" , "importtime" , "-c" , f"import { target_module } " ],
161176 capture_output = True , text = True
162177 )
163-
178+ if result .returncode != 0 :
179+ print (f"WARNING: Import failed with exit code { result .returncode } . The trace log may be incomplete or contain errors." , file = sys .stderr )
180+ if result .stdout :
181+ print (f"Worker stdout:\n { result .stdout } " , file = sys .stderr )
182+ if result .stderr :
183+ print (f"Worker stderr:\n { result .stderr } " , file = sys .stderr )
184+
164185 with open (trace_file , "w" , encoding = "utf-8" ) as f :
165186 f .write (result .stderr )
166187
0 commit comments