mirror of
https://github.com/pese-git/cherrypick.git
synced 2026-01-24 05:25:19 +00:00
Add English documentation comments to all benchmark_cherrypick source files (adapters, scenarios, CLI, reporters, runner)
This commit is contained in:
@@ -12,7 +12,13 @@ import 'package:benchmark_cherrypick/benchmarks/universal_chain_benchmark.dart';
|
|||||||
import 'package:benchmark_cherrypick/benchmarks/universal_chain_async_benchmark.dart';
|
import 'package:benchmark_cherrypick/benchmarks/universal_chain_async_benchmark.dart';
|
||||||
import 'package:benchmark_cherrypick/di_adapters/cherrypick_adapter.dart';
|
import 'package:benchmark_cherrypick/di_adapters/cherrypick_adapter.dart';
|
||||||
|
|
||||||
|
/// Command-line interface (CLI) runner for benchmarks.
|
||||||
|
///
|
||||||
|
/// Parses CLI arguments, orchestrates benchmarks for different
|
||||||
|
/// scenarios and configurations, collects results, and generates reports
|
||||||
|
/// in the desired output format.
|
||||||
class BenchmarkCliRunner {
|
class BenchmarkCliRunner {
|
||||||
|
/// Runs benchmarks based on CLI [args], configuring different test scenarios.
|
||||||
Future<void> run(List<String> args) async {
|
Future<void> run(List<String> args) async {
|
||||||
final config = parseBenchmarkCli(args);
|
final config = parseBenchmarkCli(args);
|
||||||
final results = <Map<String, dynamic>>[];
|
final results = <Map<String, dynamic>>[];
|
||||||
|
|||||||
@@ -3,15 +3,23 @@ import 'dart:io';
|
|||||||
import 'package:args/args.dart';
|
import 'package:args/args.dart';
|
||||||
import 'package:benchmark_cherrypick/scenarios/universal_chain_module.dart';
|
import 'package:benchmark_cherrypick/scenarios/universal_chain_module.dart';
|
||||||
|
|
||||||
|
/// Enum describing all supported Universal DI benchmark types.
|
||||||
enum UniversalBenchmark {
|
enum UniversalBenchmark {
|
||||||
|
/// Simple singleton registration benchmark
|
||||||
registerSingleton,
|
registerSingleton,
|
||||||
|
/// Chain of singleton dependencies
|
||||||
chainSingleton,
|
chainSingleton,
|
||||||
|
/// Chain using factories
|
||||||
chainFactory,
|
chainFactory,
|
||||||
|
/// Async chain resolution
|
||||||
chainAsync,
|
chainAsync,
|
||||||
|
/// Named registration benchmark
|
||||||
named,
|
named,
|
||||||
|
/// Override/child-scope benchmark
|
||||||
override,
|
override,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Maps [UniversalBenchmark] to the scenario enum for DI chains.
|
||||||
UniversalScenario toScenario(UniversalBenchmark b) {
|
UniversalScenario toScenario(UniversalBenchmark b) {
|
||||||
switch (b) {
|
switch (b) {
|
||||||
case UniversalBenchmark.registerSingleton:
|
case UniversalBenchmark.registerSingleton:
|
||||||
@@ -29,6 +37,7 @@ UniversalScenario toScenario(UniversalBenchmark b) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Maps benchmark to registration mode (singleton/factory/async).
|
||||||
UniversalBindingMode toMode(UniversalBenchmark b) {
|
UniversalBindingMode toMode(UniversalBenchmark b) {
|
||||||
switch (b) {
|
switch (b) {
|
||||||
case UniversalBenchmark.registerSingleton:
|
case UniversalBenchmark.registerSingleton:
|
||||||
@@ -46,6 +55,7 @@ UniversalBindingMode toMode(UniversalBenchmark b) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Utility to parse a string into its corresponding enum value [T].
|
||||||
T parseEnum<T>(String value, List<T> values, T defaultValue) {
|
T parseEnum<T>(String value, List<T> values, T defaultValue) {
|
||||||
return values.firstWhere(
|
return values.firstWhere(
|
||||||
(v) => v.toString().split('.').last.toLowerCase() == value.toLowerCase(),
|
(v) => v.toString().split('.').last.toLowerCase() == value.toLowerCase(),
|
||||||
@@ -53,15 +63,23 @@ T parseEnum<T>(String value, List<T> values, T defaultValue) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Parses comma-separated integer list from [s].
|
||||||
List<int> parseIntList(String s) =>
|
List<int> parseIntList(String s) =>
|
||||||
s.split(',').map((e) => int.tryParse(e.trim()) ?? 0).where((x) => x > 0).toList();
|
s.split(',').map((e) => int.tryParse(e.trim()) ?? 0).where((x) => x > 0).toList();
|
||||||
|
|
||||||
|
/// CLI config describing what and how to benchmark.
|
||||||
class BenchmarkCliConfig {
|
class BenchmarkCliConfig {
|
||||||
|
/// Benchmarks enabled to run (scenarios).
|
||||||
final List<UniversalBenchmark> benchesToRun;
|
final List<UniversalBenchmark> benchesToRun;
|
||||||
|
/// List of chain counts (parallel, per test).
|
||||||
final List<int> chainCounts;
|
final List<int> chainCounts;
|
||||||
|
/// List of nesting depths (max chain length, per test).
|
||||||
final List<int> nestDepths;
|
final List<int> nestDepths;
|
||||||
|
/// How many times to repeat each trial.
|
||||||
final int repeats;
|
final int repeats;
|
||||||
|
/// How many times to warm-up before measuring.
|
||||||
final int warmups;
|
final int warmups;
|
||||||
|
/// Output report format.
|
||||||
final String format;
|
final String format;
|
||||||
BenchmarkCliConfig({
|
BenchmarkCliConfig({
|
||||||
required this.benchesToRun,
|
required this.benchesToRun,
|
||||||
@@ -73,6 +91,8 @@ class BenchmarkCliConfig {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Parses CLI arguments [args] into a [BenchmarkCliConfig].
|
||||||
|
/// Supports --benchmark, --chainCount, --nestingDepth, etc.
|
||||||
BenchmarkCliConfig parseBenchmarkCli(List<String> args) {
|
BenchmarkCliConfig parseBenchmarkCli(List<String> args) {
|
||||||
final parser = ArgParser()
|
final parser = ArgParser()
|
||||||
..addOption('benchmark', abbr: 'b', defaultsTo: 'chainSingleton')
|
..addOption('benchmark', abbr: 'b', defaultsTo: 'chainSingleton')
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
import 'report_generator.dart';
|
import 'report_generator.dart';
|
||||||
|
|
||||||
|
/// Generates a CSV-formatted report for benchmark results.
|
||||||
class CsvReport extends ReportGenerator {
|
class CsvReport extends ReportGenerator {
|
||||||
|
/// List of all keys/columns to include in the CSV output.
|
||||||
@override
|
@override
|
||||||
final List<String> keys = [
|
final List<String> keys = [
|
||||||
'benchmark','chainCount','nestingDepth','mean_us','median_us','stddev_us',
|
'benchmark','chainCount','nestingDepth','mean_us','median_us','stddev_us',
|
||||||
'min_us','max_us','trials','timings_us','memory_diff_kb','delta_peak_kb','peak_rss_kb'
|
'min_us','max_us','trials','timings_us','memory_diff_kb','delta_peak_kb','peak_rss_kb'
|
||||||
];
|
];
|
||||||
|
/// Renders rows as a CSV table string.
|
||||||
@override
|
@override
|
||||||
String render(List<Map<String, dynamic>> rows) {
|
String render(List<Map<String, dynamic>> rows) {
|
||||||
final header = keys.join(',');
|
final header = keys.join(',');
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
import 'report_generator.dart';
|
import 'report_generator.dart';
|
||||||
|
|
||||||
|
/// Generates a JSON-formatted report for benchmark results.
|
||||||
class JsonReport extends ReportGenerator {
|
class JsonReport extends ReportGenerator {
|
||||||
|
/// No specific keys; outputs all fields in raw map.
|
||||||
@override
|
@override
|
||||||
List<String> get keys => [];
|
List<String> get keys => [];
|
||||||
|
/// Renders all result rows as a pretty-printed JSON array.
|
||||||
@override
|
@override
|
||||||
String render(List<Map<String, dynamic>> rows) {
|
String render(List<Map<String, dynamic>> rows) {
|
||||||
return '[\n${rows.map((r) => ' $r').join(',\n')}\n]';
|
return '[\n${rows.map((r) => ' $r').join(',\n')}\n]';
|
||||||
|
|||||||
@@ -1,11 +1,17 @@
|
|||||||
import 'report_generator.dart';
|
import 'report_generator.dart';
|
||||||
|
|
||||||
|
/// Generates a Markdown-formatted report for benchmark results.
|
||||||
|
///
|
||||||
|
/// Displays result rows as a visually clear Markdown table including a legend for all metrics.
|
||||||
class MarkdownReport extends ReportGenerator {
|
class MarkdownReport extends ReportGenerator {
|
||||||
|
/// List of columns (keys) to show in the Markdown table.
|
||||||
@override
|
@override
|
||||||
final List<String> keys = [
|
final List<String> keys = [
|
||||||
'benchmark','chainCount','nestingDepth','mean_us','median_us','stddev_us',
|
'benchmark','chainCount','nestingDepth','mean_us','median_us','stddev_us',
|
||||||
'min_us','max_us','trials','memory_diff_kb','delta_peak_kb','peak_rss_kb'
|
'min_us','max_us','trials','memory_diff_kb','delta_peak_kb','peak_rss_kb'
|
||||||
];
|
];
|
||||||
|
|
||||||
|
/// Friendly display names for each benchmark type.
|
||||||
static const nameMap = {
|
static const nameMap = {
|
||||||
'Universal_UniversalBenchmark.registerSingleton':'RegisterSingleton',
|
'Universal_UniversalBenchmark.registerSingleton':'RegisterSingleton',
|
||||||
'Universal_UniversalBenchmark.chainSingleton':'ChainSingleton',
|
'Universal_UniversalBenchmark.chainSingleton':'ChainSingleton',
|
||||||
@@ -15,6 +21,7 @@ class MarkdownReport extends ReportGenerator {
|
|||||||
'Universal_UniversalBenchmark.override':'Override',
|
'Universal_UniversalBenchmark.override':'Override',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Renders all results as a formatted Markdown table with aligned columns and a legend.
|
||||||
@override
|
@override
|
||||||
String render(List<Map<String, dynamic>> rows) {
|
String render(List<Map<String, dynamic>> rows) {
|
||||||
final headers = [
|
final headers = [
|
||||||
@@ -38,7 +45,7 @@ class MarkdownReport extends ReportGenerator {
|
|||||||
].map((cell) => cell.toString()).toList();
|
].map((cell) => cell.toString()).toList();
|
||||||
}).toList();
|
}).toList();
|
||||||
|
|
||||||
// Вычислить ширину каждой колонки
|
// Calculate column width for pretty alignment
|
||||||
final all = [headers] + dataRows;
|
final all = [headers] + dataRows;
|
||||||
final widths = List.generate(headers.length, (i) {
|
final widths = List.generate(headers.length, (i) {
|
||||||
return all.map((row) => row[i].length).reduce((a, b) => a > b ? a : b);
|
return all.map((row) => row[i].length).reduce((a, b) => a > b ? a : b);
|
||||||
|
|||||||
@@ -1,12 +1,17 @@
|
|||||||
import 'report_generator.dart';
|
import 'report_generator.dart';
|
||||||
|
|
||||||
|
/// Generates a human-readable, tab-delimited report for benchmark results.
|
||||||
|
///
|
||||||
|
/// Used for terminal and log output; shows each result as a single line with labeled headers.
|
||||||
class PrettyReport extends ReportGenerator {
|
class PrettyReport extends ReportGenerator {
|
||||||
|
/// List of columns to output in the pretty report.
|
||||||
@override
|
@override
|
||||||
final List<String> keys = [
|
final List<String> keys = [
|
||||||
'benchmark','chainCount','nestingDepth','mean_us','median_us','stddev_us',
|
'benchmark','chainCount','nestingDepth','mean_us','median_us','stddev_us',
|
||||||
'min_us','max_us','trials','memory_diff_kb','delta_peak_kb','peak_rss_kb'
|
'min_us','max_us','trials','memory_diff_kb','delta_peak_kb','peak_rss_kb'
|
||||||
];
|
];
|
||||||
|
|
||||||
|
/// Mappings from internal benchmark IDs to display names.
|
||||||
static const nameMap = {
|
static const nameMap = {
|
||||||
'Universal_UniversalBenchmark.registerSingleton': 'RegisterSingleton',
|
'Universal_UniversalBenchmark.registerSingleton': 'RegisterSingleton',
|
||||||
'Universal_UniversalBenchmark.chainSingleton': 'ChainSingleton',
|
'Universal_UniversalBenchmark.chainSingleton': 'ChainSingleton',
|
||||||
@@ -16,6 +21,7 @@ class PrettyReport extends ReportGenerator {
|
|||||||
'Universal_UniversalBenchmark.override': 'Override',
|
'Universal_UniversalBenchmark.override': 'Override',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Renders the results as a header + tab-separated value table.
|
||||||
@override
|
@override
|
||||||
String render(List<Map<String, dynamic>> rows) {
|
String render(List<Map<String, dynamic>> rows) {
|
||||||
final headers = [
|
final headers = [
|
||||||
|
|||||||
@@ -1,4 +1,9 @@
|
|||||||
|
/// Abstract base for generating benchmark result reports in different formats.
|
||||||
|
///
|
||||||
|
/// Subclasses implement [render] to output results, and [keys] to define columns (if any).
|
||||||
abstract class ReportGenerator {
|
abstract class ReportGenerator {
|
||||||
|
/// Renders the given [results] as a formatted string (table, markdown, csv, etc).
|
||||||
String render(List<Map<String, dynamic>> results);
|
String render(List<Map<String, dynamic>> results);
|
||||||
|
/// List of output columns/keys included in the export (or [] for auto/all).
|
||||||
List<String> get keys;
|
List<String> get keys;
|
||||||
}
|
}
|
||||||
@@ -3,10 +3,15 @@ import 'dart:math';
|
|||||||
import 'package:benchmark_cherrypick/benchmarks/universal_chain_benchmark.dart';
|
import 'package:benchmark_cherrypick/benchmarks/universal_chain_benchmark.dart';
|
||||||
import 'package:benchmark_cherrypick/benchmarks/universal_chain_async_benchmark.dart';
|
import 'package:benchmark_cherrypick/benchmarks/universal_chain_async_benchmark.dart';
|
||||||
|
|
||||||
|
/// Holds the results for a single benchmark execution.
|
||||||
class BenchmarkResult {
|
class BenchmarkResult {
|
||||||
|
/// List of timings for each run (in microseconds).
|
||||||
final List<num> timings;
|
final List<num> timings;
|
||||||
|
/// Difference in memory (RSS, in KB) after running.
|
||||||
final int memoryDiffKb;
|
final int memoryDiffKb;
|
||||||
|
/// Difference between peak RSS and initial RSS (in KB).
|
||||||
final int deltaPeakKb;
|
final int deltaPeakKb;
|
||||||
|
/// Peak RSS memory observed (in KB).
|
||||||
final int peakRssKb;
|
final int peakRssKb;
|
||||||
BenchmarkResult({
|
BenchmarkResult({
|
||||||
required this.timings,
|
required this.timings,
|
||||||
@@ -14,6 +19,7 @@ class BenchmarkResult {
|
|||||||
required this.deltaPeakKb,
|
required this.deltaPeakKb,
|
||||||
required this.peakRssKb,
|
required this.peakRssKb,
|
||||||
});
|
});
|
||||||
|
/// Computes a BenchmarkResult instance from run timings and memory data.
|
||||||
factory BenchmarkResult.collect({
|
factory BenchmarkResult.collect({
|
||||||
required List<num> timings,
|
required List<num> timings,
|
||||||
required List<int> rssValues,
|
required List<int> rssValues,
|
||||||
@@ -32,7 +38,10 @@ class BenchmarkResult {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Static methods to execute and time benchmarks for DI containers.
|
||||||
class BenchmarkRunner {
|
class BenchmarkRunner {
|
||||||
|
/// Runs a synchronous benchmark ([UniversalChainBenchmark]) for a given number of [warmups] and [repeats].
|
||||||
|
/// Collects execution time and observed memory.
|
||||||
static Future<BenchmarkResult> runSync({
|
static Future<BenchmarkResult> runSync({
|
||||||
required UniversalChainBenchmark benchmark,
|
required UniversalChainBenchmark benchmark,
|
||||||
required int warmups,
|
required int warmups,
|
||||||
@@ -58,6 +67,8 @@ class BenchmarkRunner {
|
|||||||
return BenchmarkResult.collect(timings: timings, rssValues: rssValues, memBefore: memBefore);
|
return BenchmarkResult.collect(timings: timings, rssValues: rssValues, memBefore: memBefore);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Runs an asynchronous benchmark ([UniversalChainAsyncBenchmark]) for a given number of [warmups] and [repeats].
|
||||||
|
/// Collects execution time and observed memory.
|
||||||
static Future<BenchmarkResult> runAsync({
|
static Future<BenchmarkResult> runAsync({
|
||||||
required UniversalChainAsyncBenchmark benchmark,
|
required UniversalChainAsyncBenchmark benchmark,
|
||||||
required int warmups,
|
required int warmups,
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
import 'package:cherrypick/cherrypick.dart';
|
import 'package:cherrypick/cherrypick.dart';
|
||||||
import 'di_adapter.dart';
|
import 'di_adapter.dart';
|
||||||
|
|
||||||
|
/// DIAdapter implementation for the CherryPick DI library.
|
||||||
|
///
|
||||||
|
/// Wraps a CherryPick [Scope] and provides methods
|
||||||
|
/// to setup modules, resolve dependencies, teardown,
|
||||||
|
/// and open nested sub-scopes for benchmarking.
|
||||||
class CherrypickDIAdapter implements DIAdapter {
|
class CherrypickDIAdapter implements DIAdapter {
|
||||||
Scope? _scope;
|
Scope? _scope;
|
||||||
|
|
||||||
@@ -37,6 +42,8 @@ class CherrypickDIAdapter implements DIAdapter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Internal adapter for a CherryPick sub-scope.
|
||||||
|
/// Used for simulating child/override DI scopes in benchmarks.
|
||||||
class _CherrypickSubScopeAdapter extends CherrypickDIAdapter {
|
class _CherrypickSubScopeAdapter extends CherrypickDIAdapter {
|
||||||
final Scope _subScope;
|
final Scope _subScope;
|
||||||
_CherrypickSubScopeAdapter(this._subScope);
|
_CherrypickSubScopeAdapter(this._subScope);
|
||||||
|
|||||||
@@ -1,9 +1,22 @@
|
|||||||
import 'package:cherrypick/cherrypick.dart';
|
import 'package:cherrypick/cherrypick.dart';
|
||||||
|
|
||||||
|
/// Abstraction for Dependency Injection (DI) Adapter.
|
||||||
|
///
|
||||||
|
/// Provides a uniform interface to setup, resolve, and teardown DI containers/modules
|
||||||
|
/// and open sub-scopes to benchmark them under different libraries.
|
||||||
abstract class DIAdapter {
|
abstract class DIAdapter {
|
||||||
|
/// Installs the provided modules into the DI container.
|
||||||
void setupModules(List<Module> modules);
|
void setupModules(List<Module> modules);
|
||||||
|
|
||||||
|
/// Resolves an instance of type [T] by optional [named] tag.
|
||||||
T resolve<T>({String? named});
|
T resolve<T>({String? named});
|
||||||
|
|
||||||
|
/// Asynchronously resolves an instance of type [T] by optional [named] tag.
|
||||||
Future<T> resolveAsync<T>({String? named});
|
Future<T> resolveAsync<T>({String? named});
|
||||||
|
|
||||||
|
/// Tears down or disposes of the DI container.
|
||||||
void teardown();
|
void teardown();
|
||||||
|
|
||||||
|
/// Opens a child DI sub-scope, useful for override/child-scope benchmarks.
|
||||||
DIAdapter openSubScope(String name);
|
DIAdapter openSubScope(String name);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,26 +1,47 @@
|
|||||||
import 'package:cherrypick/cherrypick.dart';
|
import 'package:cherrypick/cherrypick.dart';
|
||||||
import 'universal_service.dart';
|
import 'universal_service.dart';
|
||||||
|
|
||||||
|
/// Enum to represent the DI registration/binding mode.
|
||||||
enum UniversalBindingMode {
|
enum UniversalBindingMode {
|
||||||
|
/// Singleton/provider binding.
|
||||||
singletonStrategy,
|
singletonStrategy,
|
||||||
|
|
||||||
|
/// Factory-based binding.
|
||||||
factoryStrategy,
|
factoryStrategy,
|
||||||
|
|
||||||
|
/// Async-based binding.
|
||||||
asyncStrategy,
|
asyncStrategy,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Enum to represent which scenario is constructed for the benchmark.
|
||||||
enum UniversalScenario {
|
enum UniversalScenario {
|
||||||
|
/// Single registration.
|
||||||
register,
|
register,
|
||||||
|
/// Chain of dependencies.
|
||||||
chain,
|
chain,
|
||||||
|
/// Named registrations.
|
||||||
named,
|
named,
|
||||||
|
/// Child-scope override scenario.
|
||||||
override,
|
override,
|
||||||
|
/// Asynchronous chain scenario.
|
||||||
asyncChain,
|
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 {
|
class UniversalChainModule extends Module {
|
||||||
|
/// Number of chains to create.
|
||||||
final int chainCount;
|
final int chainCount;
|
||||||
|
/// Depth of each chain.
|
||||||
final int nestingDepth;
|
final int nestingDepth;
|
||||||
|
/// How modules are registered (factory/singleton/async).
|
||||||
final UniversalBindingMode bindingMode;
|
final UniversalBindingMode bindingMode;
|
||||||
|
/// Which di scenario to generate (chained, named, etc).
|
||||||
final UniversalScenario scenario;
|
final UniversalScenario scenario;
|
||||||
|
|
||||||
|
/// Constructs a configured test DI module for the benchmarks.
|
||||||
UniversalChainModule({
|
UniversalChainModule({
|
||||||
required this.chainCount,
|
required this.chainCount,
|
||||||
required this.nestingDepth,
|
required this.nestingDepth,
|
||||||
@@ -31,6 +52,7 @@ class UniversalChainModule extends Module {
|
|||||||
@override
|
@override
|
||||||
void builder(Scope currentScope) {
|
void builder(Scope currentScope) {
|
||||||
if (scenario == UniversalScenario.asyncChain) {
|
if (scenario == UniversalScenario.asyncChain) {
|
||||||
|
// Generate async chain with singleton async bindings.
|
||||||
for (var chainIndex = 0; chainIndex < chainCount; chainIndex++) {
|
for (var chainIndex = 0; chainIndex < chainCount; chainIndex++) {
|
||||||
for (var levelIndex = 0; levelIndex < nestingDepth; levelIndex++) {
|
for (var levelIndex = 0; levelIndex < nestingDepth; levelIndex++) {
|
||||||
final chain = chainIndex + 1;
|
final chain = chainIndex + 1;
|
||||||
@@ -56,15 +78,18 @@ class UniversalChainModule extends Module {
|
|||||||
|
|
||||||
switch (scenario) {
|
switch (scenario) {
|
||||||
case UniversalScenario.register:
|
case UniversalScenario.register:
|
||||||
|
// Simple singleton registration.
|
||||||
bind<UniversalService>()
|
bind<UniversalService>()
|
||||||
.toProvide(() => UniversalServiceImpl(value: 'reg', dependency: null))
|
.toProvide(() => UniversalServiceImpl(value: 'reg', dependency: null))
|
||||||
.singleton();
|
.singleton();
|
||||||
break;
|
break;
|
||||||
case UniversalScenario.named:
|
case UniversalScenario.named:
|
||||||
|
// Named factory registration for two distinct objects.
|
||||||
bind<Object>().toProvide(() => UniversalServiceImpl(value: 'impl1')).withName('impl1');
|
bind<Object>().toProvide(() => UniversalServiceImpl(value: 'impl1')).withName('impl1');
|
||||||
bind<Object>().toProvide(() => UniversalServiceImpl(value: 'impl2')).withName('impl2');
|
bind<Object>().toProvide(() => UniversalServiceImpl(value: 'impl2')).withName('impl2');
|
||||||
break;
|
break;
|
||||||
case UniversalScenario.chain:
|
case UniversalScenario.chain:
|
||||||
|
// Chain of nested services, with dependency on previous level by name.
|
||||||
for (var chainIndex = 0; chainIndex < chainCount; chainIndex++) {
|
for (var chainIndex = 0; chainIndex < chainCount; chainIndex++) {
|
||||||
for (var levelIndex = 0; levelIndex < nestingDepth; levelIndex++) {
|
for (var levelIndex = 0; levelIndex < nestingDepth; levelIndex++) {
|
||||||
final chain = chainIndex + 1;
|
final chain = chainIndex + 1;
|
||||||
|
|||||||
@@ -1,10 +1,17 @@
|
|||||||
|
|
||||||
|
/// Base interface for any universal service in the benchmarks.
|
||||||
|
///
|
||||||
|
/// Represents an object in the dependency chain with an identifiable value
|
||||||
|
/// and (optionally) a dependency on a previous service in the chain.
|
||||||
abstract class UniversalService {
|
abstract class UniversalService {
|
||||||
|
/// String ID for this service instance (e.g. chain/level info).
|
||||||
final String value;
|
final String value;
|
||||||
|
/// Optional reference to dependency service in the chain.
|
||||||
final UniversalService? dependency;
|
final UniversalService? dependency;
|
||||||
UniversalService({required this.value, this.dependency});
|
UniversalService({required this.value, this.dependency});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Default implementation for [UniversalService] used in service chains.
|
||||||
class UniversalServiceImpl extends UniversalService {
|
class UniversalServiceImpl extends UniversalService {
|
||||||
UniversalServiceImpl({required super.value, super.dependency});
|
UniversalServiceImpl({required super.value, super.dependency});
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user