@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.
@@ -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
+ }