perf: defer cli.py imports for 7.7x faster --help

Move heavy module-level imports in cli.py (console, env_utils,
code_utils, config_parser, lsp.helpers, version) into the functions
that actually use them. Split main.py imports so parse_args() is
called before loading the full stack — --help exits via argparse
before any heavy modules load.

Benchmark (Azure Standard_D4s_v5, Python 3.13, hyperfine --min-runs 30):
  --help: 297ms → 39ms (7.7x faster)
  --version: 17ms (unchanged)
This commit is contained in:
Kevin Turcios 2026-04-09 23:03:28 -05:00
parent 7351d0f0ba
commit 70e3ce1a67
2 changed files with 20 additions and 11 deletions

View file

@ -5,15 +5,6 @@ from argparse import SUPPRESS, ArgumentParser, Namespace
from functools import lru_cache
from pathlib import Path
from codeflash.cli_cmds import logging_config
from codeflash.cli_cmds.console import apologize_and_exit, logger
from codeflash.code_utils import env_utils
from codeflash.code_utils.code_utils import exit_with_message, normalize_ignore_paths
from codeflash.code_utils.config_parser import parse_config_file
from codeflash.languages.test_framework import set_current_test_framework
from codeflash.lsp.helpers import is_LSP_enabled
from codeflash.version import __version__ as version
def parse_args() -> Namespace:
parser = _build_parser()
@ -30,12 +21,17 @@ def parse_args() -> Namespace:
def process_and_validate_cmd_args(args: Namespace) -> Namespace:
from codeflash.cli_cmds import logging_config
from codeflash.cli_cmds.console import apologize_and_exit, logger
from codeflash.code_utils import env_utils
from codeflash.code_utils.code_utils import exit_with_message
from codeflash.code_utils.git_utils import (
check_running_in_git_repo,
confirm_proceeding_with_no_git_repo,
get_repo_owner_and_name,
)
from codeflash.code_utils.github_utils import require_github_app_or_exit
from codeflash.version import __version__ as version
if args.server:
os.environ["CODEFLASH_AIS_SERVER"] = args.server
@ -85,6 +81,12 @@ def process_and_validate_cmd_args(args: Namespace) -> Namespace:
def process_pyproject_config(args: Namespace) -> Namespace:
from codeflash.code_utils import env_utils
from codeflash.code_utils.code_utils import normalize_ignore_paths
from codeflash.code_utils.config_parser import parse_config_file
from codeflash.languages.test_framework import set_current_test_framework
from codeflash.lsp.helpers import is_LSP_enabled
try:
pyproject_config, pyproject_file_path = parse_config_file(args.config_file)
except ValueError as e:
@ -222,6 +224,9 @@ def project_root_from_module_root(module_root: Path, pyproject_file_path: Path)
def handle_optimize_all_arg_parsing(args: Namespace) -> Namespace:
from codeflash.cli_cmds.console import apologize_and_exit, logger
from codeflash.code_utils.code_utils import exit_with_message
if hasattr(args, "all") or (hasattr(args, "file") and args.file):
no_pr = getattr(args, "no_pr", False)

View file

@ -29,9 +29,14 @@ def main() -> None:
print(f"Codeflash version {__version__}")
return
from codeflash.cli_cmds.cli import parse_args
args = parse_args()
# Heavy imports deferred until after parse_args() so --help exits fast
from pathlib import Path
from codeflash.cli_cmds.cli import parse_args, process_pyproject_config
from codeflash.cli_cmds.cli import process_pyproject_config
from codeflash.code_utils import env_utils
from codeflash.code_utils.checkpoint import ask_should_use_checkpoint_get_functions
from codeflash.code_utils.config_parser import parse_config_file
@ -39,7 +44,6 @@ def main() -> None:
from codeflash.telemetry import posthog_cf
from codeflash.telemetry.sentry import init_sentry
args = parse_args()
if args.command != "auth":
print_codeflash_banner()