Add complex DI benchmarks, main runner, and English README with summarized results for cherrypick core

This commit is contained in:
Sergey Penkovsky
2025-08-01 08:26:33 +03:00
parent 2c1f9d5969
commit 23683119c2
9 changed files with 389 additions and 0 deletions

View File

@@ -0,0 +1,40 @@
import 'package:benchmark_harness/benchmark_harness.dart';
import 'package:cherrypick/cherrypick.dart';
class AsyncA {}
class AsyncB {
final AsyncA a;
AsyncB(this.a);
}
class AsyncC {
final AsyncB b;
AsyncC(this.b);
}
class AsyncChainModule extends Module {
@override
void builder(Scope currentScope) {
bind<AsyncA>().toProvideAsync(() async => AsyncA()).singleton();
bind<AsyncB>().toProvideAsync(() async => AsyncB(await currentScope.resolveAsync<AsyncA>())).singleton();
bind<AsyncC>().toProvideAsync(() async => AsyncC(await currentScope.resolveAsync<AsyncB>())).singleton();
}
}
class AsyncChainBenchmark extends AsyncBenchmarkBase {
AsyncChainBenchmark() : super('AsyncChain (A->B->C, async)');
late Scope scope;
@override
Future<void> setup() async {
scope = CherryPick.openRootScope();
scope.installModules([AsyncChainModule()]);
}
@override
Future<void> teardown() async {
CherryPick.closeRootScope();
}
@override
Future<void> run() async {
await scope.resolveAsync<AsyncC>();
}
}

View File

@@ -0,0 +1,37 @@
import 'package:benchmark_harness/benchmark_harness.dart';
import 'package:cherrypick/cherrypick.dart';
class AppModule extends Module {
@override
void builder(Scope currentScope) {
bind<FooService>().toProvide(() => FooService());
}
}
// Dummy service for DI
class FooService {}
class RegisterAndResolveBenchmark extends BenchmarkBase {
RegisterAndResolveBenchmark() : super('RegisterAndResolve');
late final Scope scope;
@override
void setup() {
scope = CherryPick.openRootScope();
scope.installModules([AppModule()]);
}
@override
void run() {
scope.resolve<FooService>();
}
@override
void teardown() => CherryPick.closeRootScope();
}
void main() {
RegisterAndResolveBenchmark().report();
}

View File

@@ -0,0 +1,92 @@
import 'package:benchmark_harness/benchmark_harness.dart';
import 'package:cherrypick/cherrypick.dart';
// === DI graph: A -> B -> C (singleton) ===
class ServiceA {}
class ServiceB {
final ServiceA a;
ServiceB(this.a);
}
class ServiceC {
final ServiceB b;
ServiceC(this.b);
}
class ChainSingletonModule extends Module {
@override
void builder(Scope currentScope) {
bind<ServiceA>().toProvide(() => ServiceA()).singleton();
bind<ServiceB>().toProvide((() => ServiceB(currentScope.resolve<ServiceA>()))).singleton();
bind<ServiceC>().toProvide((() => ServiceC(currentScope.resolve<ServiceB>()))).singleton();
}
}
class ChainSingletonBenchmark extends BenchmarkBase {
ChainSingletonBenchmark() : super('ChainSingleton (A->B->C, singleton)');
late Scope scope;
@override
void setup() {
scope = CherryPick.openRootScope();
scope.installModules([ChainSingletonModule()]);
}
@override
void teardown() => CherryPick.closeRootScope();
@override
void run() {
scope.resolve<ServiceC>();
}
}
// === DI graph: A -> B -> C (factory/no singleton) ===
class ChainFactoryModule extends Module {
@override
void builder(Scope currentScope) {
bind<ServiceA>().toProvide(() => ServiceA());
bind<ServiceB>().toProvide((() => ServiceB(currentScope.resolve<ServiceA>())));
bind<ServiceC>().toProvide((() => ServiceC(currentScope.resolve<ServiceB>())));
}
}
class ChainFactoryBenchmark extends BenchmarkBase {
ChainFactoryBenchmark() : super('ChainFactory (A->B->C, factory)');
late Scope scope;
@override
void setup() {
scope = CherryPick.openRootScope();
scope.installModules([ChainFactoryModule()]);
}
@override
void teardown() => CherryPick.closeRootScope();
@override
void run() {
scope.resolve<ServiceC>();
}
}
// === Named bindings: Multiple implementations ===
class Impl1 {}
class Impl2 {}
class NamedModule extends Module {
@override
void builder(Scope currentScope) {
bind<Object>().toProvide(() => Impl1()).withName('impl1');
bind<Object>().toProvide(() => Impl2()).withName('impl2');
}
}
class NamedResolveBenchmark extends BenchmarkBase {
NamedResolveBenchmark() : super('NamedResolve (by name)');
late Scope scope;
@override
void setup() {
scope = CherryPick.openRootScope();
scope.installModules([NamedModule()]);
}
@override
void teardown() => CherryPick.closeRootScope();
@override
void run() {
// Switch name for comparison
scope.resolve<Object>(named: 'impl2');
}
}

View File

@@ -0,0 +1,43 @@
import 'package:benchmark_harness/benchmark_harness.dart';
import 'package:cherrypick/cherrypick.dart';
class Shared {}
class ParentImpl extends Shared {}
class ChildImpl extends Shared {}
class ParentModule extends Module {
@override
void builder(Scope currentScope) {
bind<Shared>().toProvide(() => ParentImpl()).singleton();
}
}
class ChildOverrideModule extends Module {
@override
void builder(Scope currentScope) {
bind<Shared>().toProvide(() => ChildImpl()).singleton();
}
}
class ScopeOverrideBenchmark extends BenchmarkBase {
ScopeOverrideBenchmark() : super('ScopeOverride (child overrides parent)');
late Scope parent;
late Scope child;
@override
void setup() {
parent = CherryPick.openRootScope();
parent.installModules([ParentModule()]);
child = parent.openSubScope('child');
child.installModules([ChildOverrideModule()]);
}
@override
void teardown() {
CherryPick.closeRootScope();
}
@override
void run() {
// Должен возвращать ChildImpl, а не ParentImpl
final resolved = child.resolve<Shared>();
assert(resolved is ChildImpl);
}
}