diff --git a/cherrypick/README.md b/cherrypick/README.md index 162b2b8..f4b599d 100644 --- a/cherrypick/README.md +++ b/cherrypick/README.md @@ -94,6 +94,13 @@ final subScope = rootScope.openSubScope('featureScope') final dataBloc = await subScope.resolveAsync(); ``` +### Fast Dependency Lookup (Performance Improvement) + +> **Performance Note:** +> **Starting from version 3.0.0**, CherryPick uses a Map-based resolver index for dependency lookup. This means calls to `resolve()` and related methods are now O(1) operations, regardless of the number of modules or bindings in your scope. Previously, the library had to iterate over all modules and bindings to locate the requested dependency, which could impact performance as your project grew. +> +> This optimization is internal and does not change any library APIs or usage patterns, but it significantly improves resolution speed in larger applications. + ### Dependency Lookup API - `resolve()` — Locates a dependency instance or throws if missing. diff --git a/cherrypick/lib/src/scope.dart b/cherrypick/lib/src/scope.dart index eb157bf..55cd9ec 100644 --- a/cherrypick/lib/src/scope.dart +++ b/cherrypick/lib/src/scope.dart @@ -39,6 +39,10 @@ class Scope with CycleDetectionMixin, GlobalCycleDetectionMixin { final Set _modulesList = HashSet(); + // индекс для мгновенного поиска binding’ов + final Map> _bindingResolvers = {}; + + /// RU: Генерирует уникальный идентификатор для скоупа. /// ENG: Generates unique identifier for scope. String _generateScopeId() { @@ -96,6 +100,7 @@ class Scope with CycleDetectionMixin, GlobalCycleDetectionMixin { for (var module in modules) { module.builder(this); } + _rebuildResolversIndex(); return this; } @@ -107,7 +112,7 @@ class Scope with CycleDetectionMixin, GlobalCycleDetectionMixin { Scope dropModules() { // [AlexeyYuPopkov](https://github.com/AlexeyYuPopkov) Thank you for the [Removed exception "ConcurrentModificationError"](https://github.com/pese-git/cherrypick/pull/2) _modulesList.clear(); - + _rebuildResolversIndex(); return this; } @@ -253,17 +258,18 @@ class Scope with CycleDetectionMixin, GlobalCycleDetectionMixin { _parentScope?.tryResolveAsync(named: named, params: params); } - BindingResolver? _findBindingResolver(String? named) { + BindingResolver? _findBindingResolver(String? named) => + _bindingResolvers[T]?[named] as BindingResolver?; + + // Индексируем все binding’и после каждого installModules/dropModules + void _rebuildResolversIndex() { + _bindingResolvers.clear(); for (var module in _modulesList) { for (var binding in module.bindingSet) { - if (binding.key == T && - ((!binding.isNamed && named == null) || - (binding.isNamed && named == binding.name))) { - return binding.resolver as BindingResolver?; - } + _bindingResolvers.putIfAbsent(binding.key, () => {}); + final nameKey = binding.isNamed ? binding.name : null; + _bindingResolvers[binding.key]![nameKey] = binding.resolver!; } } - - return null; } } diff --git a/doc/full_tutorial_en.md b/doc/full_tutorial_en.md index 0ef82de..03c24b9 100644 --- a/doc/full_tutorial_en.md +++ b/doc/full_tutorial_en.md @@ -177,6 +177,14 @@ final service = scope.tryResolve(); // returns null if not exis --- +### Fast Dependency Lookup (Performance Improvement) + +> **Performance Note:** +> **Starting from version 3.0.0**, CherryPick uses a Map-based resolver index for dependency lookup. This means calls to `resolve()`, `tryResolve()` and similar methods are now O(1) operations, regardless of the number of modules or bindings within your scope. Previously it would iterate over all modules and bindings, which could reduce performance as your project grew. This optimization is internal and does not affect the public API or usage patterns, but significantly improves resolution speed for larger applications. + +--- + + ## Dependency injection with annotations & code generation CherryPick supports DI with annotations, letting you eliminate manual DI setup. diff --git a/doc/full_tutorial_ru.md b/doc/full_tutorial_ru.md index 942dbaf..9af1f20 100644 --- a/doc/full_tutorial_ru.md +++ b/doc/full_tutorial_ru.md @@ -178,6 +178,13 @@ final service = scope.tryResolve(); // вернет null, ес --- +### Быстрый поиск зависимостей (Performance Improvement) + +> **Примечание по производительности:** +> Начиная с версии **3.0.0**, CherryPick для поиска зависимости внутри scope использует Map-индекс. Благодаря этому методы `resolve()`, `tryResolve()` и аналогичные теперь работают за O(1), независимо от количества модулей и биндингов в вашем проекте. Ранее для поиска приходилось перебирать весь список вручную, что могло замедлять работу крупных приложений. Это внутреннее улучшение не меняет внешнего API или паттернов использования, но заметно ускоряет разрешение зависимостей на больших проектах. + +--- + ## Внедрение зависимостей через аннотации и автогенерацию CherryPick поддерживает DI через аннотации, что позволяет полностью избавиться от ручного внедрения зависимостей.