Skip to content

Defer inspect import to reduce import time by ~25%#1547

Open
KRRT7 wants to merge 2 commits intopython-attrs:mainfrom
KRRT7:perf/defer-inspect-import
Open

Defer inspect import to reduce import time by ~25%#1547
KRRT7 wants to merge 2 commits intopython-attrs:mainfrom
KRRT7:perf/defer-inspect-import

Conversation

@KRRT7
Copy link
Copy Markdown

@KRRT7 KRRT7 commented Apr 21, 2026

Summary

Defer the import of inspect and the loading of converters/validators submodules until first use, reducing import attr/import attrs time by ~25%.

Why: inspect costs ~12ms to import (it pulls in ast, re, enum, dis, tokenize) but is only used at class-build time. The eager import is triggered because attr/__init__.py eagerly imports validators, which uses @attrs() at module level, triggering class building → Converter()_AnnotationExtractor()import inspect.

Changes:

  1. _compat.py / _make.py: Move import inspect from module level into the methods that use it
  2. attr/__init__.py / attrs/__init__.py: Lazy-load converters and validators via the existing __getattr__ mechanism
  3. Fix _make_getattr to cache via sys.modules[mod_name].__dict__ instead of globals() so caching works correctly when called from attrs
  4. Add __dir__ to both packages so converters/validators appear in dir()

Benchmark (Azure Standard_D2s_v5, Python 3.13, 100 runs):

With bytecode Without bytecode
Baseline (main) 42.1ms ± 1.5ms 42.6ms ± 1.1ms
Optimized 31.5ms ± 1.0ms 30.8ms ± 1.2ms
Improvement 10.6ms (25%) 11.8ms (28%)

Pull Request Check List

  • I acknowledge this project's AI policy.
  • This pull request is not from my main branch.
  • There's tests for all new and changed code.
    • No new public API; existing tests cover all import patterns (from attr import converters, attr.validators, etc.)
  • Changes or additions to public APIs are reflected in our type stubs (files ending in .pyi).
    • No API changes — only deferring when existing modules are loaded.
  • The documentation has been updated.
    • No user-facing documentation changes needed (internal performance optimization).
  • Changes have news fragments in changelog.d.

Copy link
Copy Markdown
Member

@hynek hynek left a comment

Choose a reason for hiding this comment

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

There is merit to the idea but the summary is plausible-but-wrong, it both deleted and violated widely our checklist, and it contains breaking changes.

Please have a human look at it.

@KRRT7 KRRT7 force-pushed the perf/defer-inspect-import branch from 7587da9 to c3df976 Compare May 11, 2026 00:37
Move `import inspect` from module level to first use in `_compat.py`
and `_make.py`. Lazy-load `converters` and `validators` submodules
via `__getattr__` in both `attr` and `attrs` packages.

This avoids importing `inspect` (which pulls in ast, re, dis,
tokenize, etc.) at `import attr` time, reducing import time by ~25%.
@KRRT7 KRRT7 force-pushed the perf/defer-inspect-import branch from c3df976 to 37b168e Compare May 11, 2026 00:40
Copy link
Copy Markdown
Author

@KRRT7 KRRT7 left a comment

Choose a reason for hiding this comment

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

Hiya! Sorry for the noise — at the time I was testing out something internally and made a few mistakes as you can see. Now we're in a better place and it won't happen again.

Here's what's been cleaned up:

  • Checklist added back and addressed
  • Changelog fragment added (changelog.d/1547.change.md)
  • Codeflash config reverted (was unrelated)
  • Fixed a globals() bug in _make_getattr — the closure was caching into attr's dict even when called from attrs. Now uses sys.modules[mod_name].__dict__
  • Added __dir__ to both packages so converters/validators appear in dir() (they didn't on main either, but they should)
  • Added tests covering the above

CI is green. Let me know if there's anything else.

@KRRT7 KRRT7 requested a review from hynek May 11, 2026 01:05
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