Skip to content
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

Improve import time #6591

Merged
merged 51 commits into from
Nov 20, 2022
Merged
Show file tree
Hide file tree
Changes from 29 commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
6de1836
Test import time.
Dreamsorcerer Feb 3, 2022
13c30e6
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Feb 3, 2022
ec242b3
Update test_imports.py
Dreamsorcerer Feb 3, 2022
33e0ae5
Lazy load gunicorn workers.
Dreamsorcerer Feb 3, 2022
3f18cfa
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Feb 3, 2022
b9266d3
Fix type checking.
Dreamsorcerer Feb 3, 2022
3b76c1f
Merge
Dreamsorcerer Feb 3, 2022
cc3bd32
Tweak run args.
Dreamsorcerer Feb 3, 2022
cf70791
Update CHANGES/6591.misc
Dreamsorcerer Feb 3, 2022
11157ea
Update test_imports.py
Dreamsorcerer Feb 9, 2022
7a8cd02
Update test_imports.py
Dreamsorcerer Feb 9, 2022
3fcf892
Update test_imports.py
Dreamsorcerer Feb 9, 2022
79612ad
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Feb 9, 2022
98c35b1
Update test_imports.py
Dreamsorcerer Feb 9, 2022
08654c8
Update test_imports.py
Dreamsorcerer Feb 9, 2022
2d9865e
Create .coveragerc
Dreamsorcerer Feb 9, 2022
2f4c294
Update setup.cfg
Dreamsorcerer Feb 9, 2022
fd7e59d
Update test_imports.py
Dreamsorcerer Feb 9, 2022
36f8791
Update test_imports.py
Dreamsorcerer Feb 10, 2022
312e09d
Update test_imports.py
Dreamsorcerer Feb 10, 2022
a3aea8a
Update test_imports.py
Dreamsorcerer Feb 10, 2022
14aa9ea
Update ci.yml
Dreamsorcerer Feb 10, 2022
a3c8b3c
Update test_imports.py
Dreamsorcerer Feb 10, 2022
b9caa2a
Update test_imports.py
Dreamsorcerer Feb 10, 2022
a350ced
Update test_imports.py
Dreamsorcerer Feb 10, 2022
bdbf340
Update test_imports.py
Dreamsorcerer Feb 10, 2022
53de479
Update __init__.py
Dreamsorcerer Feb 10, 2022
99c3b78
Update ci.yml
Dreamsorcerer Feb 10, 2022
cbd7e18
Update tests/test_imports.py
Dreamsorcerer Feb 10, 2022
de67c15
Revert debugging
Dreamsorcerer Sep 22, 2022
877ac3b
Merge branch 'master' into importtime
Dreamsorcerer Sep 22, 2022
ca595f2
Merge branch 'master' into importtime
Dreamsorcerer Oct 29, 2022
f5ae2a3
Update test_imports.py
Dreamsorcerer Oct 29, 2022
65ac71d
Update test_imports.py
Dreamsorcerer Oct 29, 2022
94abba4
Update test_imports.py
Dreamsorcerer Oct 29, 2022
ea618a0
Update test.txt
Dreamsorcerer Oct 30, 2022
7ff29c2
Update test_imports.py
Dreamsorcerer Oct 30, 2022
d24422d
Update constraints.txt
Dreamsorcerer Oct 30, 2022
d2c8414
Update lint.txt
Dreamsorcerer Oct 30, 2022
85139ba
Update test_imports.py
Dreamsorcerer Oct 31, 2022
0e202e7
Update test_imports.py
Dreamsorcerer Oct 31, 2022
e092c14
Update test_imports.py
Dreamsorcerer Oct 31, 2022
a8dd9e8
Update test_imports.py
Dreamsorcerer Oct 31, 2022
a3dbf66
Update test_imports.py
Dreamsorcerer Oct 31, 2022
9ebc8a8
Update test_imports.py
Dreamsorcerer Oct 31, 2022
4f9d197
Merge branch 'master' into importtime
Dreamsorcerer Oct 31, 2022
fdadd38
Update __init__.py
Dreamsorcerer Oct 31, 2022
86f6eb2
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 31, 2022
57a7ec9
Update __init__.py
Dreamsorcerer Oct 31, 2022
7d87ca8
Update test_imports.py
Dreamsorcerer Oct 31, 2022
91087d2
Update test_imports.py
Dreamsorcerer Oct 31, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[run]
Dreamsorcerer marked this conversation as resolved.
Show resolved Hide resolved
branch = True
source = aiohttp, tests
omit = site-packages
1 change: 1 addition & 0 deletions CHANGES/6591.misc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Changed importing Gunicorn to happen on-demand, decreasing import time by ~53% -- :user:`Dreamsorcerer`.
32 changes: 26 additions & 6 deletions aiohttp/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
__version__ = "4.0.0a1"

from typing import Tuple
from typing import TYPE_CHECKING, Tuple

from . import hdrs as hdrs
from .client import (
Expand Down Expand Up @@ -103,6 +103,13 @@
TraceResponseChunkReceivedParams as TraceResponseChunkReceivedParams,
)

if TYPE_CHECKING:
# At runtime these are lazy-loaded at the bottom of the file.
from .worker import (
GunicornUVLoopWebWorker as GunicornUVLoopWebWorker,
GunicornWebWorker as GunicornWebWorker,
)

__all__: Tuple[str, ...] = (
"hdrs",
# client
Expand Down Expand Up @@ -203,11 +210,24 @@
"TraceRequestRedirectParams",
"TraceRequestStartParams",
"TraceResponseChunkReceivedParams",
# workers (imported lazily with __getattr__)
"GunicornUVLoopWebWorker",
"GunicornWebWorker",
)

try:
from .worker import GunicornUVLoopWebWorker, GunicornWebWorker

__all__ += ("GunicornWebWorker", "GunicornUVLoopWebWorker")
Dreamsorcerer marked this conversation as resolved.
Show resolved Hide resolved
except ImportError: # pragma: no cover
pass
def __getattr__(name: str) -> object:
global GunicornUVLoopWebWorker, GunicornWebWorker

# Importing gunicorn takes a long time (>100ms), so only import if actually needed.
if name in ("GunicornUVLoopWebWorker", "GunicornWebWorker"):
try:
from .worker import GunicornUVLoopWebWorker as guv, GunicornWebWorker as gw
except ImportError:
return None

GunicornUVLoopWebWorker = guv # type: ignore[misc]
GunicornWebWorker = gw # type: ignore[misc]
return guv if name == "GunicornUVLoopWebWorker" else gw

raise AttributeError(f"module {__name__} has no attribute {name}")
5 changes: 0 additions & 5 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -104,11 +104,6 @@ exclude_lines =
@abc.abstractmethod
@abstractmethod

[coverage:run]
branch = True
source = aiohttp, tests
omit = site-packages

[tool:pytest]
addopts =
# show 10 slowest invocations:
Expand Down
22 changes: 0 additions & 22 deletions tests/test___all__.py

This file was deleted.

45 changes: 45 additions & 0 deletions tests/test_imports.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import platform
import sys

import pytest


def test___all__(pytester: pytest.Pytester) -> None:
"""See https://github.com/aio-libs/aiohttp/issues/6197"""
Dreamsorcerer marked this conversation as resolved.
Show resolved Hide resolved
pytester.makepyfile(
test_a="""
from aiohttp import *
Dreamsorcerer marked this conversation as resolved.
Show resolved Hide resolved
assert 'GunicornWebWorker' in globals()
"""
)
result = pytester.runpytest("-vv")
if sys.platform == "win32":
print(result.outlines)
result.assert_outcomes(passed=0, errors=0)


def test_web___all__(pytester: pytest.Pytester) -> None:
pytester.makepyfile(
test_b="""
from aiohttp.web import *
Dreamsorcerer marked this conversation as resolved.
Show resolved Hide resolved
"""
)
result = pytester.runpytest("-vv")
result.assert_outcomes(passed=0, errors=0)


@pytest.mark.skipif(
not sys.platform.startswith("linux") or platform.python_implementation() == "PyPy",
reason="Timing is less reliable on other platforms",
Dreamsorcerer marked this conversation as resolved.
Show resolved Hide resolved
)
def test_import_time(pytester: pytest.Pytester) -> None:
"""Check that importing aiohttp doesn't take too long.

Obviously, the time may vary on different machines and may need to be adjusted
from time to time, but this should provide an early warning if something is
added that significantly increases import time.
"""
r = pytester.run(sys.executable, "-We", "-c", "import aiohttp", timeout=0.45)

assert not r.stdout.str()
assert not r.stderr.str()