Perf: defer heavy startup imports to reduce launch time by ~500ms#25976
Open
eendebakpt wants to merge 3 commits intospyder-ide:masterfrom
Open
Perf: defer heavy startup imports to reduce launch time by ~500ms#25976eendebakpt wants to merge 3 commits intospyder-ide:masterfrom
eendebakpt wants to merge 3 commits intospyder-ide:masterfrom
Conversation
- Remove top-level `requests` import in programs.py (saved ~250ms): only `CaseInsensitiveDict` was used in one Windows-only branch; replaced with an inline case-insensitive dict lookup using stdlib. - Defer `keyring` import in config/manager.py (saved ~200ms): keyring is only needed inside `if secure:` branches, which are hit only when remote credentials are accessed — import moved to those call sites. - Avoid importing sphinxify (sphinx+docutils+jinja2) in config/appearance.py (saved ~300ms): `CSS_PATH` is just a directory path that we now compute directly via `importlib.util.find_spec` without loading the Sphinx stack. - Defer `asyncio` import in programs.py: moved inside the `asynchronous=True` branch of `run_shell_command`, which is called only from environ.py. Total wall-clock reduction on the critical import path: spyder.utils.programs: ~440ms → ~130ms spyder.config.manager: ~616ms → ~220ms spyder.app.start: ~431ms → ~167ms Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Member
|
Hey @eendebakpt, why did you close this PR? The gains in startup time seem significant enough to merit its inclusion in our next version. |
Contributor
Author
|
@ccordoba12 PR was opened too soon by Claude. I wanted to review the PR myself first to avoid wasting reviewers resources and I wanted to validate the actual gains. Now that you are looking anyway: if change makes sense just reopen it and we can iterate until the PR is good. For python 3.15 I would recommend to adopt PEP 810 (it will help with more imports). |
- Replace importlib.util.find_spec (which can return None, triggering a type error) with osp.dirname(spyder.__file__) to derive CSS_PATH. The spyder package is always in sys.modules at this point, so this is both safe and simpler. - Remove stray # lazy import inline comments on keyring imports in config/manager.py. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Member
|
@dalthviz, please take a look at @eendebakpt's work. |
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.
Problem
Spyder's startup time was unnecessarily slow due to several third-party libraries being imported eagerly at module level, even though they are only needed lazily or in rare code paths.
Profiled using
python -X importtimeand subprocess timing.Changes
spyder/utils/programs.py— removesrequestsand defersasynciorequests(~250ms saved):CaseInsensitiveDictfromrequests.structureswas imported at module level but only used in one Windows-only branch insidealter_subprocess_kwargs_by_platform(). Replaced with an inline case-insensitive key lookup using only stdlib ({k.lower(): k for k in env}).asyncio(~100ms saved, deferred): Moved inside theif asynchronous:branch ofrun_shell_command(), which is called only fromenviron.pywithasynchronous=True.spyder/config/manager.py— deferskeyring(~200ms saved)keyringandkeyring.errors.NoKeyringErrorwere imported at the top of the module. These are only needed insideif secure:branches (get,set,remove_option), which are only hit when remote/credential-secured config options are accessed. Moved the imports to those three call sites.spyder/config/appearance.py— avoids importing sphinxify (~300ms saved)from spyder.plugins.help.utils.sphinxify import CSS_PATHwas triggering the fullsphinx+docutils+jinja2import chain at startup, just to get a path string constant. Replaced withimportlib.util.find_spec('spyder.plugins.help.utils')which resolves the path without loading the Sphinx stack.Measured improvement
spyder.utils.programsspyder.config.managerspyder.app.start🤖 Generated with Claude Code