diff --git a/benchmark_di/lib/benchmarks/universal_chain_async_benchmark.dart b/benchmark_di/lib/benchmarks/universal_chain_async_benchmark.dart index 0e7412f..eea5849 100644 --- a/benchmark_di/lib/benchmarks/universal_chain_async_benchmark.dart +++ b/benchmark_di/lib/benchmarks/universal_chain_async_benchmark.dart @@ -1,6 +1,7 @@ +import 'package:benchmark_di/scenarios/universal_binding_mode.dart'; +import 'package:benchmark_di/scenarios/universal_scenario.dart'; import 'package:benchmark_harness/benchmark_harness.dart'; import 'package:benchmark_di/di_adapters/di_adapter.dart'; -import 'package:benchmark_di/scenarios/universal_chain_module.dart'; import 'package:benchmark_di/scenarios/universal_service.dart'; class UniversalChainAsyncBenchmark extends AsyncBenchmarkBase { diff --git a/benchmark_di/lib/benchmarks/universal_chain_benchmark.dart b/benchmark_di/lib/benchmarks/universal_chain_benchmark.dart index b777bf0..b7eb19f 100644 --- a/benchmark_di/lib/benchmarks/universal_chain_benchmark.dart +++ b/benchmark_di/lib/benchmarks/universal_chain_benchmark.dart @@ -1,6 +1,7 @@ +import 'package:benchmark_di/scenarios/universal_binding_mode.dart'; +import 'package:benchmark_di/scenarios/universal_scenario.dart'; import 'package:benchmark_harness/benchmark_harness.dart'; import 'package:benchmark_di/di_adapters/di_adapter.dart'; -import 'package:benchmark_di/scenarios/universal_chain_module.dart'; import 'package:benchmark_di/scenarios/universal_service.dart'; class UniversalChainBenchmark extends BenchmarkBase { diff --git a/benchmark_di/lib/cli/benchmark_cli.dart b/benchmark_di/lib/cli/benchmark_cli.dart index 4c1ae35..1680f9d 100644 --- a/benchmark_di/lib/cli/benchmark_cli.dart +++ b/benchmark_di/lib/cli/benchmark_cli.dart @@ -1,11 +1,11 @@ import 'dart:math'; import 'package:benchmark_di/cli/report/markdown_report.dart'; +import 'package:benchmark_di/scenarios/universal_scenario.dart'; import 'package:cherrypick/cherrypick.dart'; import 'package:get_it/get_it.dart'; import 'package:riverpod/riverpod.dart' as rp; -import '../scenarios/universal_chain_module.dart'; import 'report/pretty_report.dart'; import 'report/csv_report.dart'; import 'report/json_report.dart'; diff --git a/benchmark_di/lib/cli/parser.dart b/benchmark_di/lib/cli/parser.dart index 8321bf1..3c93ede 100644 --- a/benchmark_di/lib/cli/parser.dart +++ b/benchmark_di/lib/cli/parser.dart @@ -1,7 +1,8 @@ import 'dart:io'; import 'package:args/args.dart'; -import 'package:benchmark_di/scenarios/universal_chain_module.dart'; +import 'package:benchmark_di/scenarios/universal_binding_mode.dart'; +import 'package:benchmark_di/scenarios/universal_scenario.dart'; /// Enum describing all supported Universal DI benchmark types. enum UniversalBenchmark { diff --git a/benchmark_di/lib/di_adapters/cherrypick_adapter.dart b/benchmark_di/lib/di_adapters/cherrypick_adapter.dart index 756e1ed..4cc4330 100644 --- a/benchmark_di/lib/di_adapters/cherrypick_adapter.dart +++ b/benchmark_di/lib/di_adapters/cherrypick_adapter.dart @@ -1,6 +1,129 @@ +import 'package:benchmark_di/scenarios/universal_binding_mode.dart'; +import 'package:benchmark_di/scenarios/universal_scenario.dart'; +import 'package:benchmark_di/scenarios/universal_service.dart'; import 'package:cherrypick/cherrypick.dart'; import 'di_adapter.dart'; -import '../scenarios/universal_chain_module.dart'; + + +/// Test module that generates a chain of service bindings for benchmarking. +/// +/// Configurable by chain count, nesting depth, binding mode, and scenario +/// to support various DI performance tests (singleton, factory, async, etc). +class UniversalChainModule extends Module { + /// Number of chains to create. + final int chainCount; + /// Depth of each chain. + final int nestingDepth; + /// How modules are registered (factory/singleton/async). + final UniversalBindingMode bindingMode; + /// Which di scenario to generate (chained, named, etc). + final UniversalScenario scenario; + + /// Constructs a configured test DI module for the benchmarks. + UniversalChainModule({ + required this.chainCount, + required this.nestingDepth, + this.bindingMode = UniversalBindingMode.singletonStrategy, + this.scenario = UniversalScenario.chain, + }); + + @override + void builder(Scope currentScope) { + if (scenario == UniversalScenario.asyncChain) { + // Generate async chain with singleton async bindings. + for (var chainIndex = 0; chainIndex < chainCount; chainIndex++) { + for (var levelIndex = 0; levelIndex < nestingDepth; levelIndex++) { + final chain = chainIndex + 1; + final level = levelIndex + 1; + final prevDepName = '${chain}_${level - 1}'; + final depName = '${chain}_$level'; + bind() + .toProvideAsync(() async { + final prev = level > 1 + ? await currentScope.resolveAsync(named: prevDepName) + : null; + return UniversalServiceImpl( + value: depName, + dependency: prev, + ); + }) + .withName(depName) + .singleton(); + } + } + return; + } + + switch (scenario) { + case UniversalScenario.register: + // Simple singleton registration. + bind() + .toProvide(() => UniversalServiceImpl(value: 'reg', dependency: null)) + .singleton(); + break; + case UniversalScenario.named: + // Named factory registration for two distinct objects. + bind().toProvide(() => UniversalServiceImpl(value: 'impl1')).withName('impl1'); + bind().toProvide(() => UniversalServiceImpl(value: 'impl2')).withName('impl2'); + break; + case UniversalScenario.chain: + // Chain of nested services, with dependency on previous level by name. + for (var chainIndex = 0; chainIndex < chainCount; chainIndex++) { + for (var levelIndex = 0; levelIndex < nestingDepth; levelIndex++) { + final chain = chainIndex + 1; + final level = levelIndex + 1; + final prevDepName = '${chain}_${level - 1}'; + final depName = '${chain}_$level'; + switch (bindingMode) { + case UniversalBindingMode.singletonStrategy: + bind() + .toProvide(() => UniversalServiceImpl( + value: depName, + dependency: currentScope.tryResolve(named: prevDepName), + )) + .withName(depName) + .singleton(); + break; + case UniversalBindingMode.factoryStrategy: + bind() + .toProvide(() => UniversalServiceImpl( + value: depName, + dependency: currentScope.tryResolve(named: prevDepName), + )) + .withName(depName); + break; + case UniversalBindingMode.asyncStrategy: + bind() + .toProvideAsync(() async => UniversalServiceImpl( + value: depName, + dependency: await currentScope.resolveAsync(named: prevDepName), + )) + .withName(depName) + .singleton(); + break; + } + } + } + // Регистрация алиаса без имени (на последний элемент цепочки) + final depName = '${chainCount}_$nestingDepth'; + bind() + .toProvide(() => currentScope.resolve(named: depName)) + .singleton(); + break; + case UniversalScenario.override: + // handled at benchmark level, но алиас нужен прямо в этом scope! + final depName = '${chainCount}_$nestingDepth'; + bind() + .toProvide(() => currentScope.resolve(named: depName)) + .singleton(); + break; + case UniversalScenario.asyncChain: + // already handled above + break; + } + } +} + class CherrypickDIAdapter extends DIAdapter { Scope? _scope; diff --git a/benchmark_di/lib/di_adapters/di_adapter.dart b/benchmark_di/lib/di_adapters/di_adapter.dart index 1ccfadb..938d8f9 100644 --- a/benchmark_di/lib/di_adapters/di_adapter.dart +++ b/benchmark_di/lib/di_adapters/di_adapter.dart @@ -1,5 +1,4 @@ -import 'package:benchmark_di/scenarios/universal_chain_module.dart'; - +import 'package:benchmark_di/scenarios/universal_binding_mode.dart'; /// Универсальная абстракция для DI-адаптера с унифицированной функцией регистрации. /// Теперь для каждого адаптера задаём строгий generic тип контейнера. typedef Registration = void Function(TContainer); diff --git a/benchmark_di/lib/di_adapters/get_it_adapter.dart b/benchmark_di/lib/di_adapters/get_it_adapter.dart index 051cdc5..0396161 100644 --- a/benchmark_di/lib/di_adapters/get_it_adapter.dart +++ b/benchmark_di/lib/di_adapters/get_it_adapter.dart @@ -1,4 +1,5 @@ -import 'package:benchmark_di/scenarios/universal_chain_module.dart'; +import 'package:benchmark_di/scenarios/universal_binding_mode.dart'; +import 'package:benchmark_di/scenarios/universal_scenario.dart'; import 'package:benchmark_di/scenarios/universal_service.dart'; import 'package:get_it/get_it.dart'; import 'di_adapter.dart'; diff --git a/benchmark_di/lib/di_adapters/riverpod_adapter.dart b/benchmark_di/lib/di_adapters/riverpod_adapter.dart index 2788828..c16452e 100644 --- a/benchmark_di/lib/di_adapters/riverpod_adapter.dart +++ b/benchmark_di/lib/di_adapters/riverpod_adapter.dart @@ -1,4 +1,5 @@ -import 'package:benchmark_di/scenarios/universal_chain_module.dart'; +import 'package:benchmark_di/scenarios/universal_binding_mode.dart'; +import 'package:benchmark_di/scenarios/universal_scenario.dart'; import 'package:benchmark_di/scenarios/universal_service.dart'; import 'package:riverpod/riverpod.dart' as rp; import 'di_adapter.dart'; diff --git a/benchmark_di/lib/scenarios/universal_binding_mode.dart b/benchmark_di/lib/scenarios/universal_binding_mode.dart new file mode 100644 index 0000000..4907089 --- /dev/null +++ b/benchmark_di/lib/scenarios/universal_binding_mode.dart @@ -0,0 +1,11 @@ +/// Enum to represent the DI registration/binding mode. +enum UniversalBindingMode { + /// Singleton/provider binding. + singletonStrategy, + + /// Factory-based binding. + factoryStrategy, + + /// Async-based binding. + asyncStrategy, +} diff --git a/benchmark_di/lib/scenarios/universal_chain_module.dart b/benchmark_di/lib/scenarios/universal_chain_module.dart deleted file mode 100644 index e7e3380..0000000 --- a/benchmark_di/lib/scenarios/universal_chain_module.dart +++ /dev/null @@ -1,147 +0,0 @@ -import 'package:cherrypick/cherrypick.dart'; -import 'universal_service.dart'; - -/// Enum to represent the DI registration/binding mode. -enum UniversalBindingMode { - /// Singleton/provider binding. - singletonStrategy, - - /// Factory-based binding. - factoryStrategy, - - /// Async-based binding. - asyncStrategy, -} - -/// Enum to represent which scenario is constructed for the benchmark. -enum UniversalScenario { - /// Single registration. - register, - /// Chain of dependencies. - chain, - /// Named registrations. - named, - /// Child-scope override scenario. - override, - /// Asynchronous chain scenario. - asyncChain, -} - -/// Test module that generates a chain of service bindings for benchmarking. -/// -/// Configurable by chain count, nesting depth, binding mode, and scenario -/// to support various DI performance tests (singleton, factory, async, etc). -class UniversalChainModule extends Module { - /// Number of chains to create. - final int chainCount; - /// Depth of each chain. - final int nestingDepth; - /// How modules are registered (factory/singleton/async). - final UniversalBindingMode bindingMode; - /// Which di scenario to generate (chained, named, etc). - final UniversalScenario scenario; - - /// Constructs a configured test DI module for the benchmarks. - UniversalChainModule({ - required this.chainCount, - required this.nestingDepth, - this.bindingMode = UniversalBindingMode.singletonStrategy, - this.scenario = UniversalScenario.chain, - }); - - @override - void builder(Scope currentScope) { - if (scenario == UniversalScenario.asyncChain) { - // Generate async chain with singleton async bindings. - for (var chainIndex = 0; chainIndex < chainCount; chainIndex++) { - for (var levelIndex = 0; levelIndex < nestingDepth; levelIndex++) { - final chain = chainIndex + 1; - final level = levelIndex + 1; - final prevDepName = '${chain}_${level - 1}'; - final depName = '${chain}_$level'; - bind() - .toProvideAsync(() async { - final prev = level > 1 - ? await currentScope.resolveAsync(named: prevDepName) - : null; - return UniversalServiceImpl( - value: depName, - dependency: prev, - ); - }) - .withName(depName) - .singleton(); - } - } - return; - } - - switch (scenario) { - case UniversalScenario.register: - // Simple singleton registration. - bind() - .toProvide(() => UniversalServiceImpl(value: 'reg', dependency: null)) - .singleton(); - break; - case UniversalScenario.named: - // Named factory registration for two distinct objects. - bind().toProvide(() => UniversalServiceImpl(value: 'impl1')).withName('impl1'); - bind().toProvide(() => UniversalServiceImpl(value: 'impl2')).withName('impl2'); - break; - case UniversalScenario.chain: - // Chain of nested services, with dependency on previous level by name. - for (var chainIndex = 0; chainIndex < chainCount; chainIndex++) { - for (var levelIndex = 0; levelIndex < nestingDepth; levelIndex++) { - final chain = chainIndex + 1; - final level = levelIndex + 1; - final prevDepName = '${chain}_${level - 1}'; - final depName = '${chain}_$level'; - switch (bindingMode) { - case UniversalBindingMode.singletonStrategy: - bind() - .toProvide(() => UniversalServiceImpl( - value: depName, - dependency: currentScope.tryResolve(named: prevDepName), - )) - .withName(depName) - .singleton(); - break; - case UniversalBindingMode.factoryStrategy: - bind() - .toProvide(() => UniversalServiceImpl( - value: depName, - dependency: currentScope.tryResolve(named: prevDepName), - )) - .withName(depName); - break; - case UniversalBindingMode.asyncStrategy: - bind() - .toProvideAsync(() async => UniversalServiceImpl( - value: depName, - dependency: await currentScope.resolveAsync(named: prevDepName), - )) - .withName(depName) - .singleton(); - break; - } - } - } - // Регистрация алиаса без имени (на последний элемент цепочки) - final depName = '${chainCount}_$nestingDepth'; - bind() - .toProvide(() => currentScope.resolve(named: depName)) - .singleton(); - break; - case UniversalScenario.override: - // handled at benchmark level, но алиас нужен прямо в этом scope! - final depName = '${chainCount}_$nestingDepth'; - bind() - .toProvide(() => currentScope.resolve(named: depName)) - .singleton(); - break; - case UniversalScenario.asyncChain: - // already handled above - break; - } - } -} diff --git a/benchmark_di/lib/scenarios/universal_scenario.dart b/benchmark_di/lib/scenarios/universal_scenario.dart new file mode 100644 index 0000000..59857aa --- /dev/null +++ b/benchmark_di/lib/scenarios/universal_scenario.dart @@ -0,0 +1,13 @@ +/// Enum to represent which scenario is constructed for the benchmark. +enum UniversalScenario { + /// Single registration. + register, + /// Chain of dependencies. + chain, + /// Named registrations. + named, + /// Child-scope override scenario. + override, + /// Asynchronous chain scenario. + asyncChain, +}