perf: import command modules lazily - #374
Draft
cloudsmith-iduffy wants to merge 3 commits into
Draft
Conversation
This was referenced Aug 21, 2026
Register top-level commands through a static registry. AliasGroup imports a command module on first use, so an invocation imports only the module of the invoked command. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
collect_submodules(cloudsmith_cli) bundles the modules that the lazy registry imports at run time. Exclude the test packages and conftest, which the sweep would otherwise pull in. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
cloudsmith-iduffy
force-pushed
the
perf/lazy-command-registration
branch
from
August 21, 2026 23:40
10cb6bd to
3bb922e
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Import command modules lazily. A static registry (
cli/commands/registry.py) maps each top-level command name and alias to its module, andAliasGroupimports the module on first use. An invocation now imports only the module of the invoked command.Before this change,
cli/commands/__init__.pyimported all 30 command modules on every startup so that they could self-register — the credential helpers paid forpush,upstream,mcpand every API wrapper on eachdocker pull.Results
Measured on macOS (M-series), Python 3.14.7,
PYTHONDONTWRITEBYTECODE=1(this repo's.envrcdefault). Baseline column = #373 merged.cloudsmith --versioncredential-helper docker get-X importtime)Cumulative vs master (2.72 s / 2.94 s): -90% / -88%.
Methodology (how to reproduce)
Attribute the remaining time after perf: defer the mcp import to the mcp commands #373:
cloudsmith_cli.cli.commandscost 232 ms: ~80 ms was the command modules themselves (upstream21 ms,push15 ms,mcp16 ms,credential_helper16 ms, …) and theircore/api/*imports, on top of the shareddecoratorschain (151 ms).Design constraint. Aliases and names must resolve before any module import (e.g.
cloudsmith ls, prefix matchcloudsmith whoam, DYM suggestions,--helplisting). The registry therefore duplicates the name/alias declarations statically.cli/tests/test_lazy_commands.pyimports every command module withpkgutil.walk_packagesand fails when the registry drifts from what the modules declare.Frozen binary. PyInstaller only bundles statically imported modules, so the lazy registry would silently drop every command module from the release binaries. The spec now uses
collect_submodules("cloudsmith_cli"). Verified locally with a CI-equivalent build (uv sync --locked --no-dev --no-editable --group binary --extra all, thenpyinstaller cloudsmith.spec):Behaviour checks. Full suite (800 passed, 40 skipped). Manually verified:
--helplists all commands withname|aliassuffixes and short help, alias resolution (ls), prefix match (whoam), DYM suggestions on typo, credential helper output.Type of Change
Additional Notes
cloudsmith --helpstill imports every command module (click fetches each command's short help), so--helpis as slow as before — acceptable, it is not a hot path.Flame graphs
Probe:
cloudsmith --version. Icicle charts frompython -X importtime: parents above children, width = cumulative import time. Totals include the interpreter's ownsiteimports and vary a few ms between runs.Before:
After: