diff --git a/benchmarks/di_nested.py b/benchmarks/di_nested.py index 010fa95d..4b6da670 100644 --- a/benchmarks/di_nested.py +++ b/benchmarks/di_nested.py @@ -10,7 +10,7 @@ from di import Depends from docs.src.starlette.src import App -root = generate_dag(Depends, 15, 5, 3) +root = generate_dag(Depends, 4, 3, 3) app = App() diff --git a/benchmarks/fastapi_nested.py b/benchmarks/fastapi_nested.py index febaedc6..786248ba 100644 --- a/benchmarks/fastapi_nested.py +++ b/benchmarks/fastapi_nested.py @@ -11,7 +11,7 @@ from benchmarks.utils import generate_dag -root = generate_dag(Depends, 15, 5, 3) +root = generate_dag(Depends, 4, 3, 3) app = App() @@ -24,6 +24,6 @@ async def endpoint(dag: None = Depends(root)): with TestClient(app) as client: start = time.time() - for _ in range(2): + for _ in range(50): client.get("/") print(f"{time.time()-start}") diff --git a/benchmarks/solve.py b/benchmarks/solve.py new file mode 100644 index 00000000..9ffc49db --- /dev/null +++ b/benchmarks/solve.py @@ -0,0 +1,37 @@ +"""Profile solving a DAG +""" + +import cProfile +import pstats + +from benchmarks.utils import generate_dag +from di import Container, Dependant, Depends + +root = generate_dag(Depends, 1, 1, 1) + + +async def endpoint(dag: None = Depends(root)): + return ... + + +container = Container() +solved = container.solve(Dependant(endpoint)) + + +async def bench(): + await container.execute_async(solved) + + +async def main(): + profiler = cProfile.Profile() + profiler.enable() + await bench() + profiler.disable() + stats = pstats.Stats(profiler) + stats.dump_stats(filename="bench.prof") + + +if __name__ == "__main__": + import asyncio + + asyncio.run(main()) diff --git a/di/_local_scope_context.py b/di/_local_scope_context.py index 03804859..bbddbc4f 100644 --- a/di/_local_scope_context.py +++ b/di/_local_scope_context.py @@ -12,12 +12,16 @@ class LocalScopeContext(FusedContextManager[None]): + context: contextvars.ContextVar[ContainerState] + scope: Scope + token: Optional[contextvars.Token[ContainerState]] + def __init__( self, context: contextvars.ContextVar[ContainerState], scope: Scope ) -> None: self.context = context self.scope = scope - self.token: Optional[contextvars.Token[ContainerState]] = None + self.token = None def __enter__(self): current = self.context.get() diff --git a/di/_scope_map.py b/di/_scope_map.py index ba6345ed..c95b8563 100644 --- a/di/_scope_map.py +++ b/di/_scope_map.py @@ -26,10 +26,12 @@ class ScopeMap(Generic[KT, VT]): ChainMap also doesn't allow you to set values anywhere but the left mapping, and we need to set values in arbitrary mappings. """ + mappings: Dict[Scope, Dict[KT, VT]] + __slots__ = ("mappings",) def __init__(self) -> None: - self.mappings: Dict[Scope, Dict[KT, VT]] = {} + self.mappings = {} def get(self, key: KT) -> VT: for mapping in self.mappings.values(): @@ -68,7 +70,7 @@ def pop_scope(self, scope: Scope) -> None: self.mappings.pop(scope) def copy(self) -> ScopeMap[KT, VT]: - new = ScopeMap[KT, VT]() + new = type(self)() new.mappings = self.mappings.copy() return new diff --git a/di/_state.py b/di/_state.py index b4e9d0ec..91f18db0 100644 --- a/di/_state.py +++ b/di/_state.py @@ -27,13 +27,14 @@ class ContainerState(object): - - __slots__ = ("binds", "cached_values", "stacks") + binds: Dict[DependencyProvider, DependantProtocol[Any]] + cached_values: ScopeMap[DependencyProvider, Any] + stacks: Dict[Scope, Union[AsyncExitStack, ExitStack]] def __init__(self) -> None: - self.binds: Dict[DependencyProvider, DependantProtocol[Any]] = {} - self.cached_values = ScopeMap[DependencyProvider, Any]() - self.stacks: Dict[Scope, Union[AsyncExitStack, ExitStack]] = {} + self.binds = {} + self.cached_values = ScopeMap() + self.stacks = {} def copy(self) -> "ContainerState": new = ContainerState() diff --git a/pyproject.toml b/pyproject.toml index e858883d..e62eb755 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "di" -version = "0.4.14" +version = "0.4.15" description = "Autowiring dependency injection" authors = ["Adrian Garcia Badaracco "] readme = "README.md"