mirror of
https://github.com/pese-git/cherrypick.git
synced 2026-01-23 21:13:35 +00:00
feat(benchmark_di): add yx_scope DI adapter and CLI integration
This commit is contained in:
@@ -1,6 +1,8 @@
|
|||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
|
|
||||||
import 'package:benchmark_di/cli/report/markdown_report.dart';
|
import 'package:benchmark_di/cli/report/markdown_report.dart';
|
||||||
|
import 'package:benchmark_di/di_adapters/yx_scope_adapter.dart';
|
||||||
|
import 'package:benchmark_di/di_adapters/yx_scope_universal_container.dart';
|
||||||
import 'package:benchmark_di/scenarios/universal_scenario.dart';
|
import 'package:benchmark_di/scenarios/universal_scenario.dart';
|
||||||
import 'package:cherrypick/cherrypick.dart';
|
import 'package:cherrypick/cherrypick.dart';
|
||||||
import 'package:get_it/get_it.dart';
|
import 'package:get_it/get_it.dart';
|
||||||
@@ -122,6 +124,34 @@ class BenchmarkCliRunner {
|
|||||||
repeats: config.repeats,
|
repeats: config.repeats,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
} else if (config.di == 'yx_scope') {
|
||||||
|
final di = YxScopeAdapter();
|
||||||
|
if (scenario == UniversalScenario.asyncChain) {
|
||||||
|
final benchAsync = UniversalChainAsyncBenchmark<UniversalYxScopeContainer>(
|
||||||
|
di,
|
||||||
|
chainCount: c,
|
||||||
|
nestingDepth: d,
|
||||||
|
mode: mode,
|
||||||
|
);
|
||||||
|
benchResult = await BenchmarkRunner.runAsync(
|
||||||
|
benchmark: benchAsync,
|
||||||
|
warmups: config.warmups,
|
||||||
|
repeats: config.repeats,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
final benchSync = UniversalChainBenchmark<UniversalYxScopeContainer>(
|
||||||
|
di,
|
||||||
|
chainCount: c,
|
||||||
|
nestingDepth: d,
|
||||||
|
mode: mode,
|
||||||
|
scenario: scenario,
|
||||||
|
);
|
||||||
|
benchResult = await BenchmarkRunner.runSync(
|
||||||
|
benchmark: benchSync,
|
||||||
|
warmups: config.warmups,
|
||||||
|
repeats: config.repeats,
|
||||||
|
);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
final di = CherrypickDIAdapter();
|
final di = CherrypickDIAdapter();
|
||||||
if (scenario == UniversalScenario.asyncChain) {
|
if (scenario == UniversalScenario.asyncChain) {
|
||||||
|
|||||||
126
benchmark_di/lib/di_adapters/yx_scope_adapter.dart
Normal file
126
benchmark_di/lib/di_adapters/yx_scope_adapter.dart
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
// ignore_for_file: invalid_use_of_protected_member
|
||||||
|
|
||||||
|
import 'package:benchmark_di/di_adapters/di_adapter.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:benchmark_di/di_adapters/yx_scope_universal_container.dart';
|
||||||
|
|
||||||
|
/// DIAdapter для yx_scope UniversalYxScopeContainer
|
||||||
|
class YxScopeAdapter extends DIAdapter<UniversalYxScopeContainer> {
|
||||||
|
late UniversalYxScopeContainer _scope;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void setupDependencies(void Function(UniversalYxScopeContainer container) registration) {
|
||||||
|
_scope = UniversalYxScopeContainer();
|
||||||
|
registration(_scope);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
T resolve<T extends Object>({String? named}) {
|
||||||
|
return _scope.depFor<T>(name: named).get;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<T> resolveAsync<T extends Object>({String? named}) async {
|
||||||
|
return resolve<T>(named: named);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void teardown() {
|
||||||
|
// У yx_scope нет явного dispose на ScopeContainer, но можно добавить очистку Map/Deps если потребуется
|
||||||
|
// Ничего не делаем
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
YxScopeAdapter openSubScope(String name) {
|
||||||
|
// Для простоты всегда возвращаем новый контейнер, сабскоупы не реализованы явно
|
||||||
|
return YxScopeAdapter();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> waitForAsyncReady() async {
|
||||||
|
// Все зависимости синхронны
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Registration<UniversalYxScopeContainer> universalRegistration<S extends Enum>({
|
||||||
|
required S scenario,
|
||||||
|
required int chainCount,
|
||||||
|
required int nestingDepth,
|
||||||
|
required UniversalBindingMode bindingMode,
|
||||||
|
}) {
|
||||||
|
if (scenario is UniversalScenario) {
|
||||||
|
return (scope) {
|
||||||
|
switch (scenario) {
|
||||||
|
case UniversalScenario.asyncChain:
|
||||||
|
for (int chain = 1; chain <= chainCount; chain++) {
|
||||||
|
for (int level = 1; level <= nestingDepth; level++) {
|
||||||
|
final prevDepName = '${chain}_${level - 1}';
|
||||||
|
final depName = '${chain}_$level';
|
||||||
|
final dep = scope.dep<UniversalService>(
|
||||||
|
() => UniversalServiceImpl(
|
||||||
|
value: depName,
|
||||||
|
dependency: level > 1
|
||||||
|
? scope.depFor<UniversalService>(name: prevDepName).get
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
name: depName,
|
||||||
|
);
|
||||||
|
scope.register<UniversalService>(dep, name: depName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case UniversalScenario.register:
|
||||||
|
final dep = scope.dep<UniversalService>(
|
||||||
|
() => UniversalServiceImpl(value: 'reg', dependency: null),
|
||||||
|
);
|
||||||
|
scope.register<UniversalService>(dep);
|
||||||
|
break;
|
||||||
|
case UniversalScenario.named:
|
||||||
|
final dep1 = scope.dep<UniversalService>(
|
||||||
|
() => UniversalServiceImpl(value: 'impl1'),
|
||||||
|
name: 'impl1',
|
||||||
|
);
|
||||||
|
final dep2 = scope.dep<UniversalService>(
|
||||||
|
() => UniversalServiceImpl(value: 'impl2'),
|
||||||
|
name: 'impl2',
|
||||||
|
);
|
||||||
|
scope.register<UniversalService>(dep1, name: 'impl1');
|
||||||
|
scope.register<UniversalService>(dep2, name: 'impl2');
|
||||||
|
break;
|
||||||
|
case UniversalScenario.chain:
|
||||||
|
for (int chain = 1; chain <= chainCount; chain++) {
|
||||||
|
for (int level = 1; level <= nestingDepth; level++) {
|
||||||
|
final prevDepName = '${chain}_${level - 1}';
|
||||||
|
final depName = '${chain}_$level';
|
||||||
|
final dep = scope.dep<UniversalService>(
|
||||||
|
() => UniversalServiceImpl(
|
||||||
|
value: depName,
|
||||||
|
dependency: level > 1
|
||||||
|
? scope.depFor<UniversalService>(name: prevDepName).get
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
name: depName,
|
||||||
|
);
|
||||||
|
scope.register<UniversalService>(dep, name: depName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case UniversalScenario.override:
|
||||||
|
// handled at benchmark level
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (scenario == UniversalScenario.chain || scenario == UniversalScenario.override) {
|
||||||
|
final depName = '${chainCount}_$nestingDepth';
|
||||||
|
final lastDep = scope.dep<UniversalService>(
|
||||||
|
() => scope.depFor<UniversalService>(name: depName).get,
|
||||||
|
);
|
||||||
|
scope.register<UniversalService>(lastDep);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
throw UnsupportedError('Scenario $scenario not supported by YxScopeAdapter');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
import 'package:yx_scope/yx_scope.dart';
|
||||||
|
|
||||||
|
/// Universal container for dynamic DI registration in yx_scope (for benchmarks).
|
||||||
|
/// Allows to register and resolve deps by name/type at runtime.
|
||||||
|
class UniversalYxScopeContainer extends ScopeContainer {
|
||||||
|
final Map<String, Dep<dynamic>> _namedDeps = {};
|
||||||
|
final Map<Type, Dep<dynamic>> _typedDeps = {};
|
||||||
|
|
||||||
|
void register<T>(Dep<T> dep, {String? name}) {
|
||||||
|
if (name != null) {
|
||||||
|
_namedDeps[_depKey<T>(name)] = dep;
|
||||||
|
} else {
|
||||||
|
_typedDeps[T] = dep;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Dep<T> depFor<T>({String? name}) {
|
||||||
|
if (name != null) {
|
||||||
|
final dep = _namedDeps[_depKey<T>(name)];
|
||||||
|
if (dep is Dep<T>) return dep;
|
||||||
|
throw Exception('No dep for type $T/$name');
|
||||||
|
} else {
|
||||||
|
final dep = _typedDeps[T];
|
||||||
|
if (dep is Dep<T>) return dep;
|
||||||
|
throw Exception('No dep for type $T');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static String _depKey<T>(String name) => '$T@$name';
|
||||||
|
}
|
||||||
@@ -136,5 +136,13 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.0"
|
version: "1.0.0"
|
||||||
|
yx_scope:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: yx_scope
|
||||||
|
sha256: "9ba98b442261596311363bf7361622e5ccc67189705b8d042ca23c9de366f8bf"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.1.2"
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=3.6.0 <4.0.0"
|
dart: ">=3.6.0 <4.0.0"
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ dependencies:
|
|||||||
get_it: ^8.2.0
|
get_it: ^8.2.0
|
||||||
riverpod: ^2.6.1
|
riverpod: ^2.6.1
|
||||||
kiwi: ^5.0.1
|
kiwi: ^5.0.1
|
||||||
|
yx_scope: ^1.1.2
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
lints: ^5.0.0
|
lints: ^5.0.0
|
||||||
|
|||||||
Reference in New Issue
Block a user