-
Notifications
You must be signed in to change notification settings - Fork 14
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for lazy loading and imports of some expensive subpackages and modules to speed up Perun startup time #259
Conversation
dba5714
to
8d537d3
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- If I am looking right, view is not fully lazy loaded and it was quite a source of the problems (with holoviews/bokeh being quite huge). Is that WIP?
- Can you show some numbers? Like running
perun help
,perun status
,perun init
and maybeperun showdiff
before and after? Just few runs and few numbers so we can compare how much we have saved, because it did come with a cost (worse readability, bigger complexity, and I fear it might be harder for IDEs to suggest).
Well done anyway.
@@ -94,7 +100,7 @@ def store_model_counts(analysis: list[dict[str, Any]]) -> None: | |||
@click.option( | |||
"--regression_models", | |||
"-r", | |||
type=click.Choice(regression_models.get_supported_models()), | |||
type=click.Choice(perun.utils.structs.postprocess_public.get_supported_models()), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why full name? This seems like automatic change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great, thanks for the catch. Fixed.
@@ -832,6 +834,8 @@ def set_optimization(_: click.Context, param: click.Argument, value: str) -> str | |||
:param value: value of the parameter | |||
:return: the value | |||
""" | |||
from perun.collect.trace.optimizations.optimization import Optimization |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this intended? Again it looks automatic and imports in functions are shuned by the linting.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is actually intended. Optimization
is a global object in the optimizations
module and it is too complicated to refactor it right now, as many more modules and packages would have to be lazy imported. So this is a temporary solution, similarly to how many other packages do import their nested modules in lazy_get_cli_commands
, e.g., view
, collect
, etc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add fixme there then, so we do not forget.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are many more places where local imports are used in the codebase right now before we decided to adopt the lazy-loader
approach, so this is something I definitely intend to cover in subsequent PRs regardless. However, for peace of mind, I added a TODO comment there.
perun/utils/structs/check_public.py
Outdated
@@ -0,0 +1,29 @@ | |||
from __future__ import annotations |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_public
sounds little bit weird. Maybe just call check_structs
, etc. since we have common_structs
and hence it will be uniform?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renamed.
@@ -0,0 +1,2 @@ | |||
recursive-include perun *.pyi | |||
include perun/py.typed |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is this py.typed
file? It is some stub? Can we add some comment why it is here and why it is empty? Can it contain like comment # Empty file needed for lazy_loading
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a requirement of PEP 561 and described also in mypy documentation. Packages that distribute both runtime and type stub files (.pyi
files) need to contain a py.typed
file as well to indicate support for type hints. The MANIFEST.in file is then needed for sdist distribution to include the .pyi
and py.typed
files. As the PEP does not specify what the py.typed
files should contain and it is easy enough to find an explanation for the file online, I'd just keep it empty.
Right now, view modules are being lazy loaded the naive way, i.e., by local imports in
I agree with the worse readability and bigger complexity. That is sadly the price of Python not having a native support for lazy loading. IDE, intellisense or autocomplete should not be affected, that's what the As for the numbers, I measured five runs of different commands and chose the median values:
|
This PR implements the mechanism proposed in #223 for the most expensive modules that were being imported during
perun --version
,perun import
, andperun showdiff
.