@adaas/a-concept 0.3.6 → 0.3.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +116 -78
- package/benchmarks/feature-chaining.bench.ts +465 -0
- package/benchmarks/feature-lifecycle.bench.ts +245 -0
- package/benchmarks/feature-optimize.bench.ts +205 -0
- package/benchmarks/feature-profiling.bench.ts +415 -0
- package/benchmarks/feature-template.bench.ts +211 -0
- package/benchmarks/helpers.ts +97 -0
- package/benchmarks/run-all.ts +58 -0
- package/benchmarks/scope-resolve.bench.ts +245 -0
- package/benchmarks/step-manager.bench.ts +146 -0
- package/dist/browser/index.d.mts +72 -3
- package/dist/browser/index.mjs +2 -2
- package/dist/browser/index.mjs.map +1 -1
- package/dist/node/index.cjs +244 -87
- package/dist/node/index.cjs.map +1 -1
- package/dist/node/index.d.mts +72 -3
- package/dist/node/index.d.ts +72 -3
- package/dist/node/index.mjs +244 -87
- package/dist/node/index.mjs.map +1 -1
- package/package.json +11 -1
- package/src/lib/A-Context/A-Context.class.ts +155 -60
- package/src/lib/A-Entity/A-Entity.class.ts +3 -3
- package/src/lib/A-Feature/A-Feature.class.ts +46 -41
- package/src/lib/A-Feature/A-Feature.types.ts +6 -10
- package/src/lib/A-Meta/A-Meta.class.ts +18 -3
- package/src/lib/A-Scope/A-Scope.class.ts +98 -5
- package/tests/A-Feature.test.ts +101 -0
- package/tsconfig.json +1 -0
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import Benchmark from 'benchmark';
|
|
2
|
+
import Table from 'cli-table3';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Result object collected after each benchmark completes
|
|
6
|
+
*/
|
|
7
|
+
export interface BenchResult {
|
|
8
|
+
name: string;
|
|
9
|
+
opsPerSec: string;
|
|
10
|
+
meanMs: string;
|
|
11
|
+
rme: string;
|
|
12
|
+
samples: number;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Creates and runs a Benchmark.js suite with formatted table output.
|
|
17
|
+
*
|
|
18
|
+
* @param suiteName — Human-readable group name (printed as header)
|
|
19
|
+
* @param addBenchmarks — callback that receives `suite.add(...)` bound method
|
|
20
|
+
* @returns Promise that resolves with collected results
|
|
21
|
+
*/
|
|
22
|
+
export function createSuite(
|
|
23
|
+
suiteName: string,
|
|
24
|
+
addBenchmarks: (suite: Benchmark.Suite) => void
|
|
25
|
+
): Promise<BenchResult[]> {
|
|
26
|
+
return new Promise((resolve) => {
|
|
27
|
+
const suite = new Benchmark.Suite(suiteName);
|
|
28
|
+
const results: BenchResult[] = [];
|
|
29
|
+
|
|
30
|
+
addBenchmarks(suite);
|
|
31
|
+
|
|
32
|
+
suite
|
|
33
|
+
.on('cycle', (event: Benchmark.Event) => {
|
|
34
|
+
const bench = event.target as any;
|
|
35
|
+
results.push({
|
|
36
|
+
name: bench.name,
|
|
37
|
+
opsPerSec: bench.hz.toFixed(2),
|
|
38
|
+
meanMs: (bench.stats.mean * 1000).toFixed(4),
|
|
39
|
+
rme: bench.stats.rme.toFixed(2),
|
|
40
|
+
samples: bench.stats.sample.length,
|
|
41
|
+
});
|
|
42
|
+
})
|
|
43
|
+
.on('complete', () => {
|
|
44
|
+
printTable(suiteName, results);
|
|
45
|
+
resolve(results);
|
|
46
|
+
})
|
|
47
|
+
.run({ async: false });
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Prints a formatted table of benchmark results to stdout
|
|
53
|
+
*/
|
|
54
|
+
export function printTable(title: string, results: BenchResult[]) {
|
|
55
|
+
console.log(`\n${'═'.repeat(70)}`);
|
|
56
|
+
console.log(` 📊 ${title}`);
|
|
57
|
+
console.log(`${'═'.repeat(70)}`);
|
|
58
|
+
|
|
59
|
+
const table = new Table({
|
|
60
|
+
head: ['Benchmark', 'ops/sec', 'mean (ms)', '± %', 'samples'],
|
|
61
|
+
colWidths: [40, 14, 14, 10, 10],
|
|
62
|
+
style: {
|
|
63
|
+
head: ['cyan'],
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
for (const r of results) {
|
|
68
|
+
table.push([r.name, r.opsPerSec, r.meanMs, `±${r.rme}%`, r.samples]);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
console.log(table.toString());
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Prints a summary comparison table across all suites
|
|
76
|
+
*/
|
|
77
|
+
export function printSummary(allResults: Map<string, BenchResult[]>) {
|
|
78
|
+
console.log(`\n${'═'.repeat(70)}`);
|
|
79
|
+
console.log(` 📋 PERFORMANCE SUMMARY`);
|
|
80
|
+
console.log(`${'═'.repeat(70)}`);
|
|
81
|
+
|
|
82
|
+
const table = new Table({
|
|
83
|
+
head: ['Suite', 'Benchmark', 'ops/sec', 'mean (ms)'],
|
|
84
|
+
colWidths: [25, 35, 14, 14],
|
|
85
|
+
style: {
|
|
86
|
+
head: ['green'],
|
|
87
|
+
},
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
for (const [suite, results] of allResults) {
|
|
91
|
+
for (const r of results) {
|
|
92
|
+
table.push([suite, r.name, r.opsPerSec, r.meanMs]);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
console.log(table.toString());
|
|
97
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ============================================================
|
|
3
|
+
* A-Concept Performance Benchmark Runner
|
|
4
|
+
* ============================================================
|
|
5
|
+
*
|
|
6
|
+
* Runs all benchmark suites and outputs a consolidated summary.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* npx ts-node -r tsconfig-paths/register benchmarks/run-all.ts
|
|
10
|
+
* npm run bench
|
|
11
|
+
*/
|
|
12
|
+
import { BenchResult, printSummary } from './helpers';
|
|
13
|
+
import { runStepManagerBenchmarks } from './step-manager.bench';
|
|
14
|
+
import { runFeatureTemplateBenchmarks } from './feature-template.bench';
|
|
15
|
+
import { runScopeResolveBenchmarks } from './scope-resolve.bench';
|
|
16
|
+
import { runFeatureLifecycleBenchmarks } from './feature-lifecycle.bench';
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
async function main() {
|
|
20
|
+
console.log('\n🚀 Starting A-Concept Performance Benchmarks...\n');
|
|
21
|
+
console.log(` Node.js ${process.version}`);
|
|
22
|
+
console.log(` Date: ${new Date().toISOString()}`);
|
|
23
|
+
console.log(` Platform: ${process.platform} ${process.arch}`);
|
|
24
|
+
console.log('');
|
|
25
|
+
|
|
26
|
+
const allSuites = new Map<string, BenchResult[]>();
|
|
27
|
+
|
|
28
|
+
// 1) StepManager benchmarks
|
|
29
|
+
console.log('\n📦 [1/4] A_StepsManager benchmarks...');
|
|
30
|
+
const smResults = await runStepManagerBenchmarks();
|
|
31
|
+
allSuites.set('StepManager', smResults);
|
|
32
|
+
|
|
33
|
+
// 2) Feature Template benchmarks
|
|
34
|
+
console.log('\n📦 [2/4] A_Context.featureTemplate benchmarks...');
|
|
35
|
+
const ftResults = await runFeatureTemplateBenchmarks();
|
|
36
|
+
allSuites.set('FeatureTemplate', ftResults);
|
|
37
|
+
|
|
38
|
+
// 3) Scope Resolve benchmarks
|
|
39
|
+
console.log('\n📦 [3/4] A_Scope resolve benchmarks...');
|
|
40
|
+
const srResults = await runScopeResolveBenchmarks();
|
|
41
|
+
allSuites.set('ScopeResolve', srResults);
|
|
42
|
+
|
|
43
|
+
// 4) Feature Lifecycle benchmarks
|
|
44
|
+
console.log('\n📦 [4/4] A_Feature lifecycle benchmarks...');
|
|
45
|
+
const flResults = await runFeatureLifecycleBenchmarks();
|
|
46
|
+
allSuites.set('FeatureLifecycle', flResults);
|
|
47
|
+
|
|
48
|
+
// Consolidated summary
|
|
49
|
+
printSummary(allSuites);
|
|
50
|
+
|
|
51
|
+
console.log('\n✅ All benchmarks completed.\n');
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
main().catch((err) => {
|
|
56
|
+
console.error('❌ Benchmark runner failed:', err);
|
|
57
|
+
process.exit(1);
|
|
58
|
+
});
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ============================================================
|
|
3
|
+
* A_Scope Resolve Operations Performance Benchmarks
|
|
4
|
+
* ============================================================
|
|
5
|
+
*
|
|
6
|
+
* Measures:
|
|
7
|
+
* - resolve() — single instance resolution (with parent chain traversal)
|
|
8
|
+
* - resolveConstructor() — constructor lookup by name or type
|
|
9
|
+
* - resolveAll() — batch resolution across scope hierarchy
|
|
10
|
+
* - resolveDependency() — full dependency pipeline (filters, pagination)
|
|
11
|
+
* - has() — existence checking with inheritance
|
|
12
|
+
* - register() — registration performance
|
|
13
|
+
*/
|
|
14
|
+
import { A_Component } from "@adaas/a-concept/a-component";
|
|
15
|
+
import { A_Entity } from "@adaas/a-concept/a-entity";
|
|
16
|
+
import { A_Fragment } from "@adaas/a-concept/a-fragment";
|
|
17
|
+
import { A_Scope } from "@adaas/a-concept/a-scope";
|
|
18
|
+
import { A_Dependency } from "@adaas/a-concept/a-dependency";
|
|
19
|
+
import { createSuite, BenchResult } from './helpers';
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
// ──────────────────────────────────────────────────────────────
|
|
23
|
+
// Fixture Classes
|
|
24
|
+
// ──────────────────────────────────────────────────────────────
|
|
25
|
+
|
|
26
|
+
class ComponentA extends A_Component { }
|
|
27
|
+
class ComponentB extends A_Component { }
|
|
28
|
+
class ComponentC extends A_Component { }
|
|
29
|
+
class ComponentD extends A_Component { }
|
|
30
|
+
class ComponentE extends A_Component { }
|
|
31
|
+
|
|
32
|
+
class BaseComponent extends A_Component { }
|
|
33
|
+
class DerivedComponent_A extends BaseComponent { }
|
|
34
|
+
class DerivedComponent_B extends BaseComponent { }
|
|
35
|
+
class DerivedComponent_C extends DerivedComponent_A { }
|
|
36
|
+
|
|
37
|
+
class TestEntity extends A_Entity<{ foo: string }> {
|
|
38
|
+
public foo: string = 'default';
|
|
39
|
+
|
|
40
|
+
fromNew(params: { foo: string }) {
|
|
41
|
+
this.aseid = this.generateASEID();
|
|
42
|
+
this.foo = params.foo;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
class TestFragment extends A_Fragment { }
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
// ──────────────────────────────────────────────────────────────
|
|
50
|
+
// Benchmark Suites
|
|
51
|
+
// ──────────────────────────────────────────────────────────────
|
|
52
|
+
|
|
53
|
+
export async function runScopeResolveBenchmarks(): Promise<BenchResult[]> {
|
|
54
|
+
const allResults: BenchResult[] = [];
|
|
55
|
+
|
|
56
|
+
// Suite 1: resolve() — single instance
|
|
57
|
+
const resolveResults = await createSuite('A_Scope.resolve — Single Instance', (suite) => {
|
|
58
|
+
// Flat scope
|
|
59
|
+
const flatScope = new A_Scope({
|
|
60
|
+
name: 'FlatScope',
|
|
61
|
+
components: [ComponentA, ComponentB, ComponentC, ComponentD, ComponentE]
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
// Nested scopes (3 levels)
|
|
65
|
+
const grandParent = new A_Scope({ name: 'GrandParent', components: [ComponentA] });
|
|
66
|
+
const parent = new A_Scope({ name: 'Parent', components: [ComponentB] });
|
|
67
|
+
const child = new A_Scope({ name: 'Child', components: [ComponentC] });
|
|
68
|
+
child.inherit(parent);
|
|
69
|
+
parent.inherit(grandParent);
|
|
70
|
+
|
|
71
|
+
suite
|
|
72
|
+
.add('resolve (flat, first component)', () => {
|
|
73
|
+
flatScope.resolve(ComponentA);
|
|
74
|
+
})
|
|
75
|
+
.add('resolve (flat, last component)', () => {
|
|
76
|
+
flatScope.resolve(ComponentE);
|
|
77
|
+
})
|
|
78
|
+
.add('resolve (nested, found in current)', () => {
|
|
79
|
+
child.resolve(ComponentC);
|
|
80
|
+
})
|
|
81
|
+
.add('resolve (nested, found in parent)', () => {
|
|
82
|
+
child.resolve(ComponentB);
|
|
83
|
+
})
|
|
84
|
+
.add('resolve (nested, found in grandparent)', () => {
|
|
85
|
+
child.resolve(ComponentA);
|
|
86
|
+
})
|
|
87
|
+
.add('resolve (not found)', () => {
|
|
88
|
+
flatScope.resolve(DerivedComponent_C);
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
allResults.push(...resolveResults);
|
|
92
|
+
|
|
93
|
+
// Suite 2: resolveConstructor()
|
|
94
|
+
const constructorResults = await createSuite('A_Scope.resolveConstructor', (suite) => {
|
|
95
|
+
const scope = new A_Scope({
|
|
96
|
+
name: 'ConstructorScope',
|
|
97
|
+
components: [ComponentA, DerivedComponent_A, DerivedComponent_B]
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
suite
|
|
101
|
+
.add('resolveConstructor (by class ref)', () => {
|
|
102
|
+
scope.resolveConstructor(ComponentA);
|
|
103
|
+
})
|
|
104
|
+
.add('resolveConstructor (by PascalCase name)', () => {
|
|
105
|
+
scope.resolveConstructor<ComponentA>('ComponentA');
|
|
106
|
+
})
|
|
107
|
+
.add('resolveConstructor (inherited class)', () => {
|
|
108
|
+
scope.resolveConstructor(BaseComponent);
|
|
109
|
+
})
|
|
110
|
+
.add('resolveConstructor (not found)', () => {
|
|
111
|
+
scope.resolveConstructor<ComponentE>('ComponentE');
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
allResults.push(...constructorResults);
|
|
115
|
+
|
|
116
|
+
// Suite 3: has() — existence checks
|
|
117
|
+
const hasResults = await createSuite('A_Scope.has — Existence Check', (suite) => {
|
|
118
|
+
const parentScope = new A_Scope({
|
|
119
|
+
name: 'ParentScope',
|
|
120
|
+
components: [ComponentA, ComponentB]
|
|
121
|
+
});
|
|
122
|
+
const childScope = new A_Scope({
|
|
123
|
+
name: 'ChildScope',
|
|
124
|
+
components: [ComponentC, ComponentD]
|
|
125
|
+
});
|
|
126
|
+
childScope.inherit(parentScope);
|
|
127
|
+
|
|
128
|
+
suite
|
|
129
|
+
.add('has (found in current scope)', () => {
|
|
130
|
+
childScope.has(ComponentC);
|
|
131
|
+
})
|
|
132
|
+
.add('has (found in parent scope)', () => {
|
|
133
|
+
childScope.has(ComponentA);
|
|
134
|
+
})
|
|
135
|
+
.add('has (not found anywhere)', () => {
|
|
136
|
+
childScope.has(ComponentE);
|
|
137
|
+
})
|
|
138
|
+
.add('has (by inheritance)', () => {
|
|
139
|
+
const scope = new A_Scope({
|
|
140
|
+
name: 'InheritScope',
|
|
141
|
+
components: [DerivedComponent_A]
|
|
142
|
+
});
|
|
143
|
+
scope.has(BaseComponent);
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
allResults.push(...hasResults);
|
|
147
|
+
|
|
148
|
+
// Suite 4: resolveAll() — batch resolution
|
|
149
|
+
const resolveAllResults = await createSuite('A_Scope.resolveAll — Batch Resolution', (suite) => {
|
|
150
|
+
const scope = new A_Scope({
|
|
151
|
+
name: 'BatchScope',
|
|
152
|
+
components: [DerivedComponent_A, DerivedComponent_B, DerivedComponent_C, ComponentE]
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
// Scope with entities
|
|
156
|
+
const entityScope = new A_Scope({ name: 'EntityScope' });
|
|
157
|
+
entityScope.register(TestEntity);
|
|
158
|
+
for (let i = 0; i < 20; i++) {
|
|
159
|
+
entityScope.register(new TestEntity({ foo: `val${i}` }));
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Nested scopes for resolveAll
|
|
163
|
+
const parentBatch = new A_Scope({
|
|
164
|
+
name: 'ParentBatch',
|
|
165
|
+
components: [DerivedComponent_A]
|
|
166
|
+
});
|
|
167
|
+
const childBatch = new A_Scope({
|
|
168
|
+
name: 'ChildBatch',
|
|
169
|
+
components: [DerivedComponent_B, DerivedComponent_C]
|
|
170
|
+
});
|
|
171
|
+
childBatch.inherit(parentBatch);
|
|
172
|
+
|
|
173
|
+
suite
|
|
174
|
+
.add('resolveAll (4 components, base class)', () => {
|
|
175
|
+
scope.resolveAll(BaseComponent);
|
|
176
|
+
})
|
|
177
|
+
.add('resolveAll (20 entities)', () => {
|
|
178
|
+
entityScope.resolveAll(TestEntity);
|
|
179
|
+
})
|
|
180
|
+
.add('resolveAll (nested scope)', () => {
|
|
181
|
+
childBatch.resolveAll(BaseComponent);
|
|
182
|
+
});
|
|
183
|
+
});
|
|
184
|
+
allResults.push(...resolveAllResults);
|
|
185
|
+
|
|
186
|
+
// Suite 5: resolveDependency() — full pipeline
|
|
187
|
+
const depResults = await createSuite('A_Scope.resolveDependency — Full Pipeline', (suite) => {
|
|
188
|
+
const scope = new A_Scope({
|
|
189
|
+
name: 'DepScope',
|
|
190
|
+
components: [ComponentA, ComponentB, ComponentC]
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
const entityScope = new A_Scope({ name: 'EntityDepScope' });
|
|
194
|
+
entityScope.register(TestEntity);
|
|
195
|
+
for (let i = 0; i < 10; i++) {
|
|
196
|
+
entityScope.register(new TestEntity({ foo: i < 5 ? 'bar' : 'baz' }));
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const simpleDep = new A_Dependency(ComponentA);
|
|
200
|
+
const queryDep = new A_Dependency(TestEntity, { query: { foo: 'baz' } });
|
|
201
|
+
const paginatedDep = new A_Dependency(TestEntity, { pagination: { count: 5 } });
|
|
202
|
+
|
|
203
|
+
suite
|
|
204
|
+
.add('resolveDependency (simple)', () => {
|
|
205
|
+
scope.resolveDependency(simpleDep);
|
|
206
|
+
})
|
|
207
|
+
.add('resolveDependency (with query)', () => {
|
|
208
|
+
entityScope.resolveDependency(queryDep);
|
|
209
|
+
})
|
|
210
|
+
.add('resolveDependency (with pagination)', () => {
|
|
211
|
+
entityScope.resolveDependency(paginatedDep);
|
|
212
|
+
});
|
|
213
|
+
});
|
|
214
|
+
allResults.push(...depResults);
|
|
215
|
+
|
|
216
|
+
// Suite 6: register() performance
|
|
217
|
+
const registerResults = await createSuite('A_Scope.register — Registration', (suite) => {
|
|
218
|
+
suite
|
|
219
|
+
.add('register component (class)', () => {
|
|
220
|
+
const scope = new A_Scope({ name: 'RegScope' });
|
|
221
|
+
scope.register(ComponentA);
|
|
222
|
+
})
|
|
223
|
+
.add('register entity (instance)', () => {
|
|
224
|
+
const scope = new A_Scope({ name: 'RegScope' });
|
|
225
|
+
scope.register(new TestEntity({ foo: 'test' }));
|
|
226
|
+
})
|
|
227
|
+
.add('register 5 components', () => {
|
|
228
|
+
const scope = new A_Scope({ name: 'RegScope' });
|
|
229
|
+
scope.register(ComponentA);
|
|
230
|
+
scope.register(ComponentB);
|
|
231
|
+
scope.register(ComponentC);
|
|
232
|
+
scope.register(ComponentD);
|
|
233
|
+
scope.register(ComponentE);
|
|
234
|
+
});
|
|
235
|
+
});
|
|
236
|
+
allResults.push(...registerResults);
|
|
237
|
+
|
|
238
|
+
return allResults;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
// Run standalone
|
|
243
|
+
if (require.main === module) {
|
|
244
|
+
runScopeResolveBenchmarks().catch(console.error);
|
|
245
|
+
}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ============================================================
|
|
3
|
+
* A_StepsManager Performance Benchmarks
|
|
4
|
+
* ============================================================
|
|
5
|
+
*
|
|
6
|
+
* Measures:
|
|
7
|
+
* - Constructor + unique ID assignment
|
|
8
|
+
* - Graph building + topological sort (toSortedArray)
|
|
9
|
+
* - Full pipeline: steps → stages (toStages)
|
|
10
|
+
* - Scaling behavior with increasing step counts
|
|
11
|
+
*/
|
|
12
|
+
import { A_Component } from "@adaas/a-concept/a-component";
|
|
13
|
+
import { A_Dependency } from "@adaas/a-concept/a-dependency";
|
|
14
|
+
import { A_StepsManager } from "@adaas/a-concept/a-step-manager";
|
|
15
|
+
import { A_Feature } from "@adaas/a-concept/a-feature";
|
|
16
|
+
import { A_Scope } from "@adaas/a-concept/a-scope";
|
|
17
|
+
import { createSuite, BenchResult } from './helpers';
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
// ──────────────────────────────────────────────────────────────
|
|
21
|
+
// Fixture Helpers
|
|
22
|
+
// ──────────────────────────────────────────────────────────────
|
|
23
|
+
|
|
24
|
+
class BenchComponent extends A_Component {
|
|
25
|
+
async step1() { }
|
|
26
|
+
async step2() { }
|
|
27
|
+
async step3() { }
|
|
28
|
+
async step4() { }
|
|
29
|
+
async step5() { }
|
|
30
|
+
async step6() { }
|
|
31
|
+
async step7() { }
|
|
32
|
+
async step8() { }
|
|
33
|
+
async step9() { }
|
|
34
|
+
async step10() { }
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function makeSteps(count: number, opts: { withDeps?: boolean } = {}) {
|
|
38
|
+
const steps: any[] = [];
|
|
39
|
+
for (let i = 0; i < count; i++) {
|
|
40
|
+
const step: any = {
|
|
41
|
+
name: `step${i}`,
|
|
42
|
+
dependency: new A_Dependency(BenchComponent),
|
|
43
|
+
handler: `step${i}`,
|
|
44
|
+
};
|
|
45
|
+
if (opts.withDeps && i > 0) {
|
|
46
|
+
step.after = `BenchComponent.step${i - 1}`;
|
|
47
|
+
}
|
|
48
|
+
steps.push(step);
|
|
49
|
+
}
|
|
50
|
+
return steps;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
// ──────────────────────────────────────────────────────────────
|
|
55
|
+
// Benchmark Suites
|
|
56
|
+
// ──────────────────────────────────────────────────────────────
|
|
57
|
+
|
|
58
|
+
export async function runStepManagerBenchmarks(): Promise<BenchResult[]> {
|
|
59
|
+
const allResults: BenchResult[] = [];
|
|
60
|
+
|
|
61
|
+
// Suite 1: Constructor performance
|
|
62
|
+
const constructorResults = await createSuite('A_StepsManager — Constructor', (suite) => {
|
|
63
|
+
const steps6 = makeSteps(6);
|
|
64
|
+
const steps20 = makeSteps(20);
|
|
65
|
+
const steps50 = makeSteps(50);
|
|
66
|
+
|
|
67
|
+
suite
|
|
68
|
+
.add('new A_StepsManager(6 steps)', () => {
|
|
69
|
+
new A_StepsManager(steps6);
|
|
70
|
+
})
|
|
71
|
+
.add('new A_StepsManager(20 steps)', () => {
|
|
72
|
+
new A_StepsManager(steps20);
|
|
73
|
+
})
|
|
74
|
+
.add('new A_StepsManager(50 steps)', () => {
|
|
75
|
+
new A_StepsManager(steps50);
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
allResults.push(...constructorResults);
|
|
79
|
+
|
|
80
|
+
// Suite 2: Topological sort
|
|
81
|
+
const sortResults = await createSuite('A_StepsManager — toSortedArray', (suite) => {
|
|
82
|
+
const steps6 = makeSteps(6);
|
|
83
|
+
const steps6Deps = makeSteps(6, { withDeps: true });
|
|
84
|
+
const steps20 = makeSteps(20);
|
|
85
|
+
const steps20Deps = makeSteps(20, { withDeps: true });
|
|
86
|
+
const steps50 = makeSteps(50);
|
|
87
|
+
|
|
88
|
+
suite
|
|
89
|
+
.add('toSortedArray (6 steps, no deps)', () => {
|
|
90
|
+
const sm = new A_StepsManager(steps6);
|
|
91
|
+
sm.toSortedArray();
|
|
92
|
+
})
|
|
93
|
+
.add('toSortedArray (6 steps, chained)', () => {
|
|
94
|
+
const sm = new A_StepsManager(steps6Deps);
|
|
95
|
+
sm.toSortedArray();
|
|
96
|
+
})
|
|
97
|
+
.add('toSortedArray (20 steps, no deps)', () => {
|
|
98
|
+
const sm = new A_StepsManager(steps20);
|
|
99
|
+
sm.toSortedArray();
|
|
100
|
+
})
|
|
101
|
+
.add('toSortedArray (20 steps, chained)', () => {
|
|
102
|
+
const sm = new A_StepsManager(steps20Deps);
|
|
103
|
+
sm.toSortedArray();
|
|
104
|
+
})
|
|
105
|
+
.add('toSortedArray (50 steps, no deps)', () => {
|
|
106
|
+
const sm = new A_StepsManager(steps50);
|
|
107
|
+
sm.toSortedArray();
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
allResults.push(...sortResults);
|
|
111
|
+
|
|
112
|
+
// Suite 3: toStages (full pipeline)
|
|
113
|
+
const stagesResults = await createSuite('A_StepsManager — toStages', (suite) => {
|
|
114
|
+
const scope = new A_Scope({ name: 'BenchScope', components: [BenchComponent] });
|
|
115
|
+
const steps6 = makeSteps(6);
|
|
116
|
+
const steps20 = makeSteps(20);
|
|
117
|
+
|
|
118
|
+
suite
|
|
119
|
+
.add('toStages (6 steps)', () => {
|
|
120
|
+
const component = scope.resolve(BenchComponent)!;
|
|
121
|
+
const feature = new A_Feature({
|
|
122
|
+
name: 'benchFeature',
|
|
123
|
+
scope: new A_Scope(),
|
|
124
|
+
template: steps6,
|
|
125
|
+
});
|
|
126
|
+
// toStages is called internally during construction
|
|
127
|
+
})
|
|
128
|
+
.add('toStages (20 steps)', () => {
|
|
129
|
+
const component = scope.resolve(BenchComponent)!;
|
|
130
|
+
const feature = new A_Feature({
|
|
131
|
+
name: 'benchFeature',
|
|
132
|
+
scope: new A_Scope(),
|
|
133
|
+
template: steps20,
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
allResults.push(...stagesResults);
|
|
138
|
+
|
|
139
|
+
return allResults;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
// Run standalone
|
|
144
|
+
if (require.main === module) {
|
|
145
|
+
runStepManagerBenchmarks().catch(console.error);
|
|
146
|
+
}
|