Skip to content

MAINT: Lazy Imports for perf#1668

Merged
rlundeen2 merged 11 commits intomicrosoft:mainfrom
rlundeen2:users/rlundeen/2026_04_29_lazy_import
Apr 30, 2026
Merged

MAINT: Lazy Imports for perf#1668
rlundeen2 merged 11 commits intomicrosoft:mainfrom
rlundeen2:users/rlundeen/2026_04_29_lazy_import

Conversation

@rlundeen2
Copy link
Copy Markdown
Contributor

@rlundeen2 rlundeen2 commented Apr 29, 2026

Uses PEP 562 getattr-based lazy imports in init.py files to defer expensive third-party dependencies (transformers, scipy, openai, PIL, azure.storage.blob, httpx, pandas, huggingface_hub) until first use.

Also defers frontend_core import in pyrit_scan.py to after arg parsing so --help and bad arguments skip the full framework load entirely.

Command Before After
pyrit_scan --help ~12s ~0.4s
pyrit_scan --list-scenarios ~12s ~6.8s

Also added a test to prevent some heavy model import regressions.

rlundeen2 and others added 3 commits April 29, 2026 11:02
Use PEP 562 __getattr__-based lazy imports in four __init__.py files
to defer loading of heavy third-party dependencies until first use:

- prompt_target: HuggingFaceChatTarget (defers transformers ~4s)
- prompt_converter: 5 audio converters (defers scipy ~1.3s),
  TextJailbreakConverter (defers datasets/pandas ~0.5s)
- score: 19 symbols for audio/video scorers and scorer_evaluation
  (defers av, pandas, scipy.stats)
- common: 5 download_hf_model functions (defers huggingface_hub ~0.3s)

Reduces pyrit_scan --list-scenarios wall-clock time from ~12s to ~5.4s
(~55% improvement).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Layer 1: Make 4 symbols lazy in pyrit/common/__init__.py:
- convert_local_image_to_data_url (defers pyrit.models -> openai, azure.storage.blob)
- display_image_response (defers PIL, pyrit.memory -> sqlalchemy)
- get_httpx_client, make_request_and_raise_if_error_async (defers httpx)
This cuts 'import pyrit' from ~4s to ~0.3s, benefiting all CLI entry points.

Layer 2: Defer frontend_core in pyrit_scan.py:
- Import from _cli_args directly for arg parsing (already lightweight)
- Move frontend_core import inside main() after parse_args()
- Move 'Starting PyRIT...' print after arg parsing

Result: pyrit_scan --help goes from ~5.4s to ~0.36s.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Document two patterns for performance-sensitive imports:
- PEP 562 __getattr__ lazy loading in __init__.py files
- Deferred imports in CLI entry points for instant --help

Also add guidance in Performance Considerations section for when
to use lazy imports (modules with heavy third-party deps on the
CLI startup path).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@rlundeen2 rlundeen2 marked this pull request as draft April 29, 2026 18:38
rlundeen2 and others added 5 commits April 29, 2026 11:39
Document two patterns for performance-sensitive imports:
- PEP 562 __getattr__ lazy loading in __init__.py files
- Deferred imports in CLI entry points for instant --help

Also add guidance in Performance Considerations section for when
to use lazy imports (modules with heavy third-party deps on the
CLI startup path).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Instead of PEP 562 lazy loading in pyrit/common/__init__.py, simply
don't re-export heavy submodules (data_url_converter, display_response,
net_utility, download_hf_model).  Consumers now import directly from
the specific file, which is more readable and has the same perf benefit.

Updated the 5 files that imported convert_local_image_to_data_url via
pyrit.common to import from pyrit.common.data_url_converter instead.
The other symbols already had direct imports everywhere.

Also updated the style guide: 'Keeping __init__.py Startup Fast' now
describes both the direct-import pattern (for internal packages) and
the __getattr__ pattern (for public API packages).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- storage_io.py: Defer azure.storage.blob, azure.core.exceptions, and
  pyrit.auth into AzureBlobStorageIO methods (saves ~1.37s for DiskStorageIO
  users who never need azure)
- memory_interface.py: Defer pyrit.memory.migration (alembic ~1.07s) into
  _run_schema_migration() and reset_database(); defer memory_embedding
  (openai ~1.16s) into enable_embedding()
- score/__init__.py: Move scorer_metrics/scorer_metrics_io (no heavy deps)
  back to eager imports, keeping only truly heavy symbols lazy
- Update test patch paths for relocated imports

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Subprocess-based tests verify that heavy modules (transformers, azure SDK,
alembic, openai, pandas, scipy, av) are NOT loaded at key import points:
- CLI arg parsing (ensures --help stays ~0.3s)
- import pyrit (ensures package stays lightweight)
- PromptTarget base class (ensures ML deps stay lazy)

Also updates style guide to document deferred imports in internal modules
as an allowed pattern for heavy optional dependencies.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@rlundeen2 rlundeen2 marked this pull request as ready for review April 29, 2026 22:14
rlundeen2 and others added 3 commits April 30, 2026 09:08
Subprocess-based tests verify that heavy modules (transformers, azure SDK,
alembic, openai, pandas, scipy, av) are NOT loaded at key import points:
- CLI arg parsing (ensures --help stays ~0.3s)
- import pyrit (ensures package stays lightweight)
- PromptTarget base class (ensures ML deps stay lazy)

Also updates style guide to document deferred imports in internal modules
as an allowed pattern for heavy optional dependencies.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…b.com/rlundeen2/PyRIT into users/rlundeen/2026_04_29_lazy_import

# Conflicts:
#	.github/instructions/style-guide.instructions.md
…4_29_lazy_import

# Conflicts:
#	pyrit/models/storage_io.py
@rlundeen2 rlundeen2 enabled auto-merge April 30, 2026 16:45
@rlundeen2 rlundeen2 added this pull request to the merge queue Apr 30, 2026
Merged via the queue into microsoft:main with commit 7065339 Apr 30, 2026
48 checks passed
@rlundeen2 rlundeen2 deleted the users/rlundeen/2026_04_29_lazy_import branch April 30, 2026 17:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants