|
9 | 9 | import os |
10 | 10 | import sys |
11 | 11 | import timeit |
| 12 | +from concurrent.futures import ThreadPoolExecutor |
12 | 13 |
|
13 | 14 | from knack.cli import CLI |
14 | 15 | from knack.commands import CLICommandsLoader |
@@ -258,31 +259,48 @@ def _update_command_table_from_modules(args, command_modules=None): |
258 | 259 | logger.debug("Loading command modules:") |
259 | 260 | logger.debug(self.header_mod) |
260 | 261 |
|
261 | | - for mod in [m for m in command_modules if m not in BLOCKED_MODS]: |
| 262 | + print(f"*** Starting SUT***") |
| 263 | + start_time_wrapper = timeit.default_timer() |
| 264 | + |
| 265 | + def load_module_threaded(mod): |
262 | 266 | try: |
263 | 267 | start_time = timeit.default_timer() |
264 | 268 | module_command_table, module_group_table = _load_module_command_loader(self, args, mod) |
265 | 269 | import_module_breaking_changes(mod) |
266 | | - for cmd in module_command_table.values(): |
267 | | - cmd.command_source = mod |
268 | | - self.command_table.update(module_command_table) |
269 | | - self.command_group_table.update(module_group_table) |
270 | | - |
271 | 270 | elapsed_time = timeit.default_timer() - start_time |
272 | | - logger.debug(self.item_format_string, mod, elapsed_time, |
273 | | - len(module_group_table), len(module_command_table)) |
274 | | - count += 1 |
275 | | - cumulative_elapsed_time += elapsed_time |
276 | | - cumulative_group_count += len(module_group_table) |
277 | | - cumulative_command_count += len(module_command_table) |
| 271 | + return (mod, module_command_table, module_group_table, elapsed_time, None) |
278 | 272 | except Exception as ex: # pylint: disable=broad-except |
279 | | - # Changing this error message requires updating CI script that checks for failed |
280 | | - # module loading. |
281 | | - from azure.cli.core import telemetry |
282 | | - logger.error("Error loading command module '%s': %s", mod, ex) |
283 | | - telemetry.set_exception(exception=ex, fault_type='module-load-error-' + mod, |
284 | | - summary='Error loading module: {}'.format(mod)) |
285 | | - logger.debug(traceback.format_exc()) |
| 273 | + return (mod, {}, {}, 0, ex) |
| 274 | + |
| 275 | + # Use ThreadPoolExecutor to load modules in parallel |
| 276 | + with ThreadPoolExecutor(max_workers=4) as executor: |
| 277 | + futures = [executor.submit(load_module_threaded, mod) |
| 278 | + for mod in command_modules if mod not in BLOCKED_MODS] |
| 279 | + |
| 280 | + for future in futures: |
| 281 | + mod, module_command_table, module_group_table, elapsed_time, error = future.result() |
| 282 | + if error: |
| 283 | + # Changing this error message requires updating CI script that checks for failed |
| 284 | + # module loading. |
| 285 | + from azure.cli.core import telemetry |
| 286 | + logger.error("Error loading command module '%s': %s", mod, error) |
| 287 | + telemetry.set_exception(exception=error, fault_type='module-load-error-' + mod, |
| 288 | + summary='Error loading module: {}'.format(mod)) |
| 289 | + logger.debug(traceback.format_exc()) |
| 290 | + else: |
| 291 | + for cmd in module_command_table.values(): |
| 292 | + cmd.command_source = mod |
| 293 | + self.command_table.update(module_command_table) |
| 294 | + self.command_group_table.update(module_group_table) |
| 295 | + |
| 296 | + logger.debug(self.item_format_string, mod, elapsed_time, |
| 297 | + len(module_group_table), len(module_command_table)) |
| 298 | + count += 1 |
| 299 | + cumulative_elapsed_time += elapsed_time |
| 300 | + cumulative_group_count += len(module_group_table) |
| 301 | + cumulative_command_count += len(module_command_table) |
| 302 | + elapsed_time = timeit.default_timer() - start_time_wrapper |
| 303 | + print(f"*** SUT operation *** took: {elapsed_time:.6f} seconds for {len(command_modules)} modules") |
286 | 304 | # Summary line |
287 | 305 | logger.debug(self.item_format_string, |
288 | 306 | "Total ({})".format(count), cumulative_elapsed_time, |
|
0 commit comments