Skip to content

Conversation

@DanielMicrosoft
Copy link
Contributor

@DanielMicrosoft DanielMicrosoft commented Dec 10, 2025

Related command

Description

ADO task: https://msazure.visualstudio.com/One/_workitems/edit/35856522

This PR aims to speed up the time it takes to re-build the commandIndex. This is currently a major bottleneck to performance.

The most expensive operations in that code path have had concurrency applied using threads (where possible).

Testing scenarios:

  • General commands (az help, version, upgrade, etc).
  • Top-level commands (vm create, etc).
  • Command no found errors
  • Tab completion
  • re-building/writing commandIndex.json (when it doesnt exist)
  • re-building/writing commandIndex.json (PATCH)
  • az help correctly generates command tree.
  • Log output from _update_command_table_from_modules is unchanged
  • Try with extensions installed

Testing Guide

History Notes

[Component Name 1] BREAKING CHANGE: az command a: Make some customer-facing breaking change
[Component Name 2] az command b: Add some customer-facing feature


This checklist is used to make sure that common guidelines for a pull request are followed.

@azure-client-tools-bot-prd
Copy link

azure-client-tools-bot-prd bot commented Dec 10, 2025

️✔️AzureCLI-FullTest
️✔️acr
️✔️latest
️✔️3.12
️✔️3.13
️✔️acs
️✔️latest
️✔️3.12
️✔️3.13
️✔️advisor
️✔️latest
️✔️3.12
️✔️3.13
️✔️ams
️✔️latest
️✔️3.12
️✔️3.13
️✔️apim
️✔️latest
️✔️3.12
️✔️3.13
️✔️appconfig
️✔️latest
️✔️3.12
️✔️3.13
️✔️appservice
️✔️latest
️✔️3.12
️✔️3.13
️✔️aro
️✔️latest
️✔️3.12
️✔️3.13
️✔️backup
️✔️latest
️✔️3.12
️✔️3.13
️✔️batch
️✔️latest
️✔️3.12
️✔️3.13
️✔️batchai
️✔️latest
️✔️3.12
️✔️3.13
️✔️billing
️✔️latest
️✔️3.12
️✔️3.13
️✔️botservice
️✔️latest
️✔️3.12
️✔️3.13
️✔️cdn
️✔️latest
️✔️3.12
️✔️3.13
️✔️cloud
️✔️latest
️✔️3.12
️✔️3.13
️✔️cognitiveservices
️✔️latest
️✔️3.12
️✔️3.13
️✔️compute_recommender
️✔️latest
️✔️3.12
️✔️3.13
️✔️computefleet
️✔️latest
️✔️3.12
️✔️3.13
️✔️config
️✔️latest
️✔️3.12
️✔️3.13
️✔️configure
️✔️latest
️✔️3.12
️✔️3.13
️✔️consumption
️✔️latest
️✔️3.12
️✔️3.13
️✔️container
️✔️latest
️✔️3.12
️✔️3.13
️✔️containerapp
️✔️latest
️✔️3.12
️✔️3.13
️✔️core
️✔️latest
️✔️3.12
️✔️3.13
️✔️cosmosdb
️✔️latest
️✔️3.12
️✔️3.13
️✔️databoxedge
️✔️latest
️✔️3.12
️✔️3.13
️✔️dls
️✔️latest
️✔️3.12
️✔️3.13
️✔️dms
️✔️latest
️✔️3.12
️✔️3.13
️✔️eventgrid
️✔️latest
️✔️3.12
️✔️3.13
️✔️eventhubs
️✔️latest
️✔️3.12
️✔️3.13
️✔️feedback
️✔️latest
️✔️3.12
️✔️3.13
️✔️find
️✔️latest
️✔️3.12
️✔️3.13
️✔️hdinsight
️✔️latest
️✔️3.12
️✔️3.13
️✔️identity
️✔️latest
️✔️3.12
️✔️3.13
️✔️iot
️✔️latest
️✔️3.12
️✔️3.13
️✔️keyvault
️✔️latest
️✔️3.12
️✔️3.13
️✔️lab
️✔️latest
️✔️3.12
️✔️3.13
️✔️managedservices
️✔️latest
️✔️3.12
️✔️3.13
️✔️maps
️✔️latest
️✔️3.12
️✔️3.13
️✔️marketplaceordering
️✔️latest
️✔️3.12
️✔️3.13
️✔️monitor
️✔️latest
️✔️3.12
️✔️3.13
️✔️mysql
️✔️latest
️✔️3.12
️✔️3.13
️✔️netappfiles
️✔️latest
️✔️3.12
️✔️3.13
️✔️network
️✔️latest
️✔️3.12
️✔️3.13
️✔️policyinsights
️✔️latest
️✔️3.12
️✔️3.13
️✔️postgresql
️✔️latest
️✔️3.12
️✔️3.13
️✔️privatedns
️✔️latest
️✔️3.12
️✔️3.13
️✔️profile
️✔️latest
️✔️3.12
️✔️3.13
️✔️rdbms
️✔️latest
️✔️3.12
️✔️3.13
️✔️redis
️✔️latest
️✔️3.12
️✔️3.13
️✔️relay
️✔️latest
️✔️3.12
️✔️3.13
️✔️resource
️✔️latest
️✔️3.12
️✔️3.13
️✔️role
️✔️latest
️✔️3.12
️✔️3.13
️✔️search
️✔️latest
️✔️3.12
️✔️3.13
️✔️security
️✔️latest
️✔️3.12
️✔️3.13
️✔️servicebus
️✔️latest
️✔️3.12
️✔️3.13
️✔️serviceconnector
️✔️latest
️✔️3.12
️✔️3.13
️✔️servicefabric
️✔️latest
️✔️3.12
️✔️3.13
️✔️signalr
️✔️latest
️✔️3.12
️✔️3.13
️✔️sql
️✔️latest
️✔️3.12
️✔️3.13
️✔️sqlvm
️✔️latest
️✔️3.12
️✔️3.13
️✔️storage
️✔️latest
️✔️3.12
️✔️3.13
️✔️synapse
️✔️latest
️✔️3.12
️✔️3.13
️✔️telemetry
️✔️latest
️✔️3.12
️✔️3.13
️✔️util
️✔️latest
️✔️3.12
️✔️3.13
️✔️vm
️✔️latest
️✔️3.12
️✔️3.13

@azure-client-tools-bot-prd
Copy link

azure-client-tools-bot-prd bot commented Dec 10, 2025

️✔️AzureCLI-BreakingChangeTest
️✔️Non Breaking Changes

@github-actions
Copy link

The git hooks are available for azure-cli and azure-cli-extensions repos. They could help you run required checks before creating the PR.

Please sync the latest code with latest dev branch (for azure-cli) or main branch (for azure-cli-extensions).
After that please run the following commands to enable git hooks:

pip install azdev --upgrade
azdev setup -c <your azure-cli repo path> -r <your azure-cli-extensions repo path>

@yonzhan
Copy link
Collaborator

yonzhan commented Dec 10, 2025

Thank you for your contribution! We will review the pull request and get back to you soon.

@DanielMicrosoft
Copy link
Contributor Author

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 3 pipeline(s).

@DanielMicrosoft
Copy link
Contributor Author

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 3 pipeline(s).

@DanielMicrosoft DanielMicrosoft marked this pull request as ready for review December 16, 2025 02:54
Copilot AI review requested due to automatic review settings December 16, 2025 02:55
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces concurrent module loading using ThreadPoolExecutor to improve Azure CLI command table build performance. The changes parallelize the expensive operation of loading command modules, which is currently a major bottleneck.

Key changes:

  • Command modules are now loaded concurrently using threads with a configurable timeout and worker count
  • Module loading logic has been refactored into smaller methods for better organization
  • A new test ensures command table integrity after the threading changes

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 5 comments.

File Description
src/azure-cli-core/azure/cli/core/init.py Implements ThreadPoolExecutor-based concurrent module loading with timeout protection, refactors module loading into separate methods (_load_modules, _load_single_module, _process_successful_load, etc.), and adds configuration constants for timeout and thread count
src/azure-cli-core/azure/cli/core/tests/test_command_table_integrity.py Adds integration test to verify command table integrity, checking for duplicates, core command groups, structural integrity, and proper command source attribution

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

import traceback
try:
start_time = timeit.default_timer()
module_command_table, module_group_table = _load_module_command_loader(self, args, mod)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a risk of race conditions when loading command_loader with multiple threads? How can we ensure that all loaders are properly registered and that each command is correctly mapped to its corresponding loader?

loader.loaders.append(command_loader) # This will be used by interactive

loader.cmd_to_loader_map[cmd] = [command_loader]

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

great catch @MoChilia , I believe I have addressed those concerns by changing the setup to have the threads only return a result, and the parent thread only will do the object mutation.

Interested in your feedback 👍

@yonzhan yonzhan removed this from the January 2026 (2026-01-13) milestone Jan 6, 2026
@jiasli
Copy link
Member

jiasli commented Jan 15, 2026

Can you show some example BEFORE/AFTER for commands such as az version, az vm create --help, etc?

@DanielMicrosoft
Copy link
Contributor Author

Can you show some example BEFORE/AFTER for commands such as az version, az vm create --help, etc?

Hey @jiasli , please check this Loop doc here, I've added relevant commands that are effected by it.

If you can think of others to add please let me know.

@jiasli jiasli assigned DanielMicrosoft and unassigned jiasli Jan 19, 2026
@jiasli
Copy link
Member

jiasli commented Jan 19, 2026

My understanding is that the 6.517 seconds execution time of az version only happens during warm-up. Once the command index is built, it will no longer be built again for subsequent command executions, so subsequent command executions won't benefit from this improvement, right?

@DanielMicrosoft DanielMicrosoft force-pushed the 35856522-improve-command-index-perf branch from de7a573 to 8b414bd Compare January 20, 2026 00:44
cmd_tbl = loader.load_command_table(["extra", "extra", "positional_argument"])
self.assertDictEqual(INDEX[CommandIndex._COMMAND_INDEX], self.expected_command_index)
self.assertEqual(list(cmd_tbl), ['hello mod-only', 'hello overridden', 'extra final', 'hello ext-only'])
self.assertSetEqual(set(cmd_tbl), {'hello mod-only', 'hello overridden', 'extra final', 'hello ext-only'})
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As commands are loaded non-deterministically now, the order of them when converting a dict to a list may change, so changing to a set here, afaik this is not functionally important (as commands are invoked by key, not by order of registation). So changing to a set here is fine.

@DanielMicrosoft
Copy link
Contributor Author

My understanding is that the 6.517 seconds execution time of az version only happens during warm-up. Once the command index is built, it will no longer be built again for subsequent command executions, so subsequent command executions won't benefit from this improvement, right?

There are various scenarios that will trigger the rebuild:

  • After CLI version upgrades
  • After extension install/update/uninstall
  • When cloud profile changes [az cloud set]
  • When the index is corrupted or missing
  • Top-level help az help
  • Command not found scenarios.

We have added a telemetry property to track when a rebuild happens:
props["context.default.azurecli.iscmdidxrebuildtriggered"]

Around 30% of az version calls on Windows/Linux will trigger a rebuild (see here: Link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Auto-Assign Auto assign by bot Core CLI core infrastructure

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants