perf: defer imports + runtime micro-optimizations in hot paths#13
Open
KRRT7 wants to merge 3 commits intoperf/architectural-winsfrom
Open
perf: defer imports + runtime micro-optimizations in hot paths#13KRRT7 wants to merge 3 commits intoperf/architectural-winsfrom
KRRT7 wants to merge 3 commits intoperf/architectural-winsfrom
Conversation
- Add `from __future__ import annotations` to color.py - Move `from colorsys import rgb_to_hls` to inline in downgrade() - Move `from ._palettes import ...` to inline in get_truecolor() and downgrade() — palette data only needed at runtime, not import time - Move `from .terminal_theme import DEFAULT_TERMINAL_THEME` to inline in get_truecolor() — only needed as default arg fallback - Move `Result` to TYPE_CHECKING (annotation-only with future annotations) These are all loaded on cache misses in LRU-cached methods, so the inline import overhead is negligible after warmup.
Remove `re` from module-level imports in all files on the Console import path (color.py, text.py, markup.py, _wrap.py, _emoji_replace.py, highlighter.py). Regex patterns are now compiled lazily on first use via module-level sentinels. Also move `typing.Match` and `typing.Pattern` (which trigger `re` import) to TYPE_CHECKING blocks, and replace three `rgb(...)` color strings in default_styles.py with `Color.from_rgb()` to avoid regex-based Color.parse(). This eliminates `re` (and its `_sre`, `re._compiler`, `re._parser`, `re._constants` dependencies) from the `from rich.console import Console` import chain entirely.
- Style.__eq__/__ne__: add identity shortcut (`is`) before hash comparison - Style.combine/chain: use _add (LRU-cached) directly instead of sum() which goes through __add__ + redundant .copy() check per iteration - Segment.simplify: check `is` before `==` for style comparison since adjacent segments very often share the exact same Style object
This was referenced Apr 9, 2026
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.
Stacked on #12.
E2E Import Time (hyperfine, 30+ runs, Standard_D2s_v5)
CPython 3.12 (typing imports re — deferral doesn't help)
ConsoleRichHandlerCPython 3.13 (typing no longer imports re — full benefit)
ConsoleRichHandlerRuntime Micro-benchmarks (Standard_D2s_v5, Python 3.13.13)
What this adds (on top of #12)
color.py — deferred imports
from __future__ import annotationscolorsys,_palettes,terminal_themeto first use inget_truecolor()/downgrade()(both LRU-cached)ResulttoTYPE_CHECKINGDefer
remodule from Console import chain (7 files)RE_COLORcompiled lazily inColor.parse()(LRU-cached)_re_whitespacecompiled lazily on firstrstrip_end(); inlineimport reinhighlight_regex(),highlight_words(),split(),detect_indentation(),with_indent_guides()RE_TAGSvia_compile_tags(),RE_HANDLERlazy inrender(), escape regex lazy inescape(); addfrom __future__ import annotations, moveMatchtoTYPE_CHECKING_EMOJI_SUBglobal; moveMatchtoTYPE_CHECKINGre_word→ lazy_re_wordinwords()import removed insideJSONHighlighter.highlight()rgb(...)color strings →Color.from_rgb()to avoid regex-basedColor.parse()at import timeRuntime micro-optimizations in hot paths
Style.__eq__/__ne__: add identity shortcut (is) before hash comparison — skips hash computation when comparing the same cached object (very common in the render pipeline)Style.combine/chain: use_add(LRU-cached) directly instead ofsum()which routes through__add__+ redundant.copy()check per iterationSegment.simplify: checkisbefore==for style comparison — adjacent segments very often share the exact same Style object referenceTesting
pytest tests/— 952 passed, 25 skippedtests/test_markup.pyto use_compile_tags()instead of removedRE_TAGSmodule constant