@nestia/benchmark 14.0.0 → 14.0.2
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 +1 -1
- package/lib/DynamicBenchmarker.d.ts +238 -8
- package/lib/DynamicBenchmarker.js +221 -64
- package/lib/DynamicBenchmarker.js.map +1 -1
- package/lib/IBenchmarkEvent.d.ts +19 -0
- package/lib/internal/DynamicBenchmarkReporter.d.ts +50 -1
- package/lib/internal/DynamicBenchmarkReporter.js +43 -18
- package/lib/internal/DynamicBenchmarkReporter.js.map +1 -1
- package/lib/internal/DynamicBenchmarkStatistics.d.ts +25 -0
- package/lib/internal/DynamicBenchmarkStatistics.js +51 -0
- package/lib/internal/DynamicBenchmarkStatistics.js.map +1 -0
- package/lib/internal/IBenchmarkMaster.d.ts +26 -0
- package/lib/internal/IBenchmarkServant.d.ts +19 -0
- package/package.json +4 -3
- package/src/DynamicBenchmarker.ts +395 -104
- package/src/IBenchmarkEvent.ts +24 -0
- package/src/internal/DynamicBenchmarkReporter.ts +71 -16
- package/src/internal/DynamicBenchmarkStatistics.ts +62 -0
- package/src/internal/IBenchmarkMaster.ts +27 -0
- package/src/internal/IBenchmarkServant.ts +19 -0
|
@@ -47,9 +47,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
47
47
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
48
48
|
exports.DynamicBenchmarker = void 0;
|
|
49
49
|
const fs_1 = __importDefault(require("fs"));
|
|
50
|
+
const os_1 = __importDefault(require("os"));
|
|
51
|
+
const path_1 = __importDefault(require("path"));
|
|
50
52
|
const tgrid_1 = require("tgrid");
|
|
51
53
|
const tstl_1 = require("tstl");
|
|
52
54
|
const DynamicBenchmarkReporter_1 = require("./internal/DynamicBenchmarkReporter");
|
|
55
|
+
const DynamicBenchmarkStatistics_1 = require("./internal/DynamicBenchmarkStatistics");
|
|
53
56
|
/**
|
|
54
57
|
* Dynamic benchmark executor running prefixed functions.
|
|
55
58
|
*
|
|
@@ -75,12 +78,46 @@ const DynamicBenchmarkReporter_1 = require("./internal/DynamicBenchmarkReporter"
|
|
|
75
78
|
* Additionally, if you hope to see some utilization cases, see the below
|
|
76
79
|
* example tagged links.
|
|
77
80
|
*
|
|
81
|
+
* Processing cost: Totals are split across T servants once; E events are
|
|
82
|
+
* aggregated with hash-based endpoint grouping. Progress notifications update
|
|
83
|
+
* the aggregate from one servant counter delta in constant time. Event
|
|
84
|
+
* statistics and rendering traverse their input populations; discovery visits
|
|
85
|
+
* each real directory once.
|
|
86
|
+
*
|
|
87
|
+
* Computation reuse: A master distributes distinct request budgets rather than
|
|
88
|
+
* replaying one effectful request. Endpoint grouping shares one event
|
|
89
|
+
* population across whole-run and endpoint statistics. Results are not cached
|
|
90
|
+
* across benchmark runs because server state and timing change.
|
|
91
|
+
*
|
|
92
|
+
* Resource ownership: Each master owns at most threads connectors and
|
|
93
|
+
* simultaneous function workers; connector closure is attempted on
|
|
94
|
+
* connection/execution success or failure; a rejected close is suppressed and
|
|
95
|
+
* may leave an unreleased child process. Events retained by servants/master
|
|
96
|
+
* scale with logged events, and memory samples with run duration. The
|
|
97
|
+
* independent sampler detaches its report target on stop or rejection and
|
|
98
|
+
* clears/wakes its owned timer. A pending caller memory getter has no
|
|
99
|
+
* cancellation hook, but its task retains only the sampler state/getter and
|
|
100
|
+
* cannot keep the master report arrays, connectors or event collections through
|
|
101
|
+
* that state. Its eventual result is discarded after deactivation. Returned
|
|
102
|
+
* reports transfer their arrays to callers.
|
|
103
|
+
*
|
|
104
|
+
* Platform boundary: WorkerConnector process mode owns Node child-process
|
|
105
|
+
* launch/IPC and its explicit stdio modes. Feature discovery resolves the
|
|
106
|
+
* caller location with native path and fs realpath/stat, follows directory
|
|
107
|
+
* links with realpath cycle detection and imports discovered native absolute
|
|
108
|
+
* paths. It does not infer filesystem case policy from OS names.
|
|
109
|
+
*
|
|
78
110
|
* @author Jeongho Nam - https://github.com/samchon
|
|
79
111
|
* @example
|
|
80
112
|
* https://github.com/samchon/nestia-start/blob/master/test/benchmaark/index.ts
|
|
81
113
|
*
|
|
82
114
|
* @example
|
|
83
115
|
* https://github.com/samchon/backend/blob/master/test/benchmark/index.ts
|
|
116
|
+
*
|
|
117
|
+
* @evidence contracts/common.md#principled-implementation The master spawns one child process per thread through tgrid's process-mode `WorkerConnector`, drives each servant over RPC, and merges the returned events; totals are split by floor plus remainder so the shares sum to the requested count and simultaneous budget.
|
|
118
|
+
* @evidence contracts/common.md#clear-and-simple-design One namespace is the public surface (master, servant, markdown, props, report); execution, discovery, and cleanup helpers stay private, and statistics and rendering live in their own internal namespaces.
|
|
119
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts Nothing names a server, feature, or file: the feature extension, prefix, and filter are caller inputs, and the servant path is a property rather than an assumed location.
|
|
120
|
+
* @evidence contracts/common.md#meaningful-documentation The namespace prose explains the two-program model, what each program does, and how to obtain markdown, with links to the member documentation and to example repositories.
|
|
84
121
|
*/
|
|
85
122
|
var DynamicBenchmarker;
|
|
86
123
|
(function (DynamicBenchmarker) {
|
|
@@ -92,55 +129,106 @@ var DynamicBenchmarker;
|
|
|
92
129
|
* Note that, {@link IMasterProps.servant} property must be the path of the
|
|
93
130
|
* servant program executing the {@link servant} function.
|
|
94
131
|
*
|
|
132
|
+
* The servants are child processes. When a servant fails to connect or to
|
|
133
|
+
* execute, every servant receives a close attempt before the returned promise
|
|
134
|
+
* rejects.
|
|
135
|
+
*
|
|
136
|
+
* Processing cost: Totals are split across T servants once; E events are
|
|
137
|
+
* aggregated with hash-based endpoint grouping. Progress notifications update
|
|
138
|
+
* the aggregate from one servant counter delta in constant time. Event
|
|
139
|
+
* statistics and rendering traverse their input populations; discovery visits
|
|
140
|
+
* each real directory once.
|
|
141
|
+
*
|
|
142
|
+
* Computation reuse: A master distributes distinct request budgets rather
|
|
143
|
+
* than replaying one effectful request. Endpoint grouping shares one event
|
|
144
|
+
* population across whole-run and endpoint statistics. Results are not cached
|
|
145
|
+
* across benchmark runs because server state and timing change.
|
|
146
|
+
*
|
|
147
|
+
* Resource ownership: Each master owns at most threads connectors and
|
|
148
|
+
* simultaneous function workers; connector closure is attempted on
|
|
149
|
+
* connection/execution success or failure; a rejected close is suppressed and
|
|
150
|
+
* may leave an unreleased child process. Events retained by servants/master
|
|
151
|
+
* scale with logged events, and memory samples with run duration. The
|
|
152
|
+
* independent sampler detaches its report target on stop or rejection and
|
|
153
|
+
* clears/wakes its owned timer. A pending caller memory getter has no
|
|
154
|
+
* cancellation hook, but its task retains only the sampler state/getter and
|
|
155
|
+
* cannot keep the master report arrays, connectors or event collections
|
|
156
|
+
* through that state. Its eventual result is discarded after deactivation.
|
|
157
|
+
* Returned reports transfer their arrays to callers.
|
|
158
|
+
*
|
|
159
|
+
* Platform boundary: WorkerConnector process mode owns Node child-process
|
|
160
|
+
* launch/IPC and its explicit stdio modes. Feature discovery resolves the
|
|
161
|
+
* caller location with native path and fs realpath/stat, follows directory
|
|
162
|
+
* links with realpath cycle detection and imports discovered native absolute
|
|
163
|
+
* paths. It does not infer filesystem case policy from OS names.
|
|
164
|
+
*
|
|
95
165
|
* @param props Properties of the master program
|
|
96
166
|
* @returns Benchmark report
|
|
167
|
+
* @evidence contracts/common.md#principled-implementation Inputs are validated as safe integers before any process starts; totals are distributed by floor plus remainder; servants execute concurrently and every event is grouped by method and path template in a hash map; closing is attempted for every spawned servant on success and on failure, and the memory sampler is deactivated when the run ends, detaching its report array and clearing/waking its owned timer immediately; a pending caller getter may settle later but cannot append.
|
|
168
|
+
* @evidence contracts/common.md#clear-and-simple-design One function owns the run and keeps the sequence readable: validate, spawn, sample, execute, close, aggregate; statistics come from `DynamicBenchmarkStatistics` and the closing helper is shared by the failure and success paths.
|
|
169
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts A servant that fails to close cannot alter a finished report and is not allowed to hide the run's own error, so closing failures are dropped on purpose; no other error is swallowed except a rejecting memory getter, which ends sampling as documented.
|
|
170
|
+
* @evidence contracts/common.md#meaningful-documentation The comment states what the master does, that the servant property must name the servant program, that servants are child processes, and that every servant receives a close attempt before a failure rejects.
|
|
97
171
|
*/
|
|
98
172
|
DynamicBenchmarker.master = (props) => __awaiter(this, void 0, void 0, function* () {
|
|
99
|
-
var _a;
|
|
173
|
+
var _a, _b;
|
|
100
174
|
if (!Number.isSafeInteger(props.count) || props.count < 0)
|
|
101
175
|
throw new Error("DynamicBenchmarker.master(): count must be a non-negative integer.");
|
|
102
176
|
if (!Number.isSafeInteger(props.threads) || props.threads <= 0)
|
|
103
177
|
throw new Error("DynamicBenchmarker.master(): threads must be a positive integer.");
|
|
104
178
|
if (!Number.isSafeInteger(props.simultaneous) || props.simultaneous <= 0)
|
|
105
179
|
throw new Error("DynamicBenchmarker.master(): simultaneous must be a positive integer.");
|
|
180
|
+
if (props.simultaneous < props.threads)
|
|
181
|
+
throw new Error(`DynamicBenchmarker.master(): simultaneous (${props.simultaneous}) must not be less than threads (${props.threads}), as each servant runs at least one request at a time.`);
|
|
106
182
|
const completes = new Array(props.threads).fill(0);
|
|
107
|
-
|
|
183
|
+
let completed = 0;
|
|
184
|
+
// the first `total % threads` servants take one more than the rest, so the
|
|
185
|
+
// shares sum to the total
|
|
186
|
+
const distribute = (total) => new Array(props.threads)
|
|
108
187
|
.fill(0)
|
|
109
|
-
.map((_, index) => Math.floor(
|
|
110
|
-
(index <
|
|
111
|
-
const
|
|
188
|
+
.map((_, index) => Math.floor(total / props.threads) +
|
|
189
|
+
(index < total % props.threads ? 1 : 0));
|
|
190
|
+
const counts = distribute(props.count);
|
|
191
|
+
const budgets = distribute(props.simultaneous);
|
|
192
|
+
// every servant is a child process, so each connector created must be
|
|
193
|
+
// closed on every path out of this function, including a failed connection
|
|
194
|
+
// of a sibling
|
|
195
|
+
const spawned = [];
|
|
196
|
+
const settled = yield Promise.allSettled(new Array(props.threads).fill(null).map((_, i) => __awaiter(this, void 0, void 0, function* () {
|
|
112
197
|
var _a;
|
|
113
198
|
const connector = new tgrid_1.WorkerConnector(null, {
|
|
114
199
|
filter: (_a = props.filter) !== null && _a !== void 0 ? _a : (() => true),
|
|
115
200
|
progress: (current) => {
|
|
201
|
+
completed += current - completes[i];
|
|
116
202
|
completes[i] = current;
|
|
117
203
|
if (props.progress)
|
|
118
|
-
props.progress(
|
|
204
|
+
props.progress(completed);
|
|
119
205
|
},
|
|
120
206
|
}, "process");
|
|
207
|
+
spawned.push(connector);
|
|
121
208
|
yield connector.connect(props.servant, { stdio: props.stdio });
|
|
122
|
-
return connector;
|
|
123
209
|
})));
|
|
210
|
+
const refused = settled.find((result) => result.status === "rejected");
|
|
211
|
+
if (refused !== undefined) {
|
|
212
|
+
yield closeAll(spawned);
|
|
213
|
+
throw refused.reason;
|
|
214
|
+
}
|
|
215
|
+
const servants = spawned;
|
|
124
216
|
const started_at = new Date();
|
|
125
217
|
const memories = [];
|
|
126
|
-
let completed_at
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
simultaneous: Math.ceil(props.simultaneous / props.threads),
|
|
141
|
-
})))).flat();
|
|
142
|
-
completed_at = new Date();
|
|
143
|
-
yield Promise.all(servants.map((connector) => connector.close()));
|
|
218
|
+
let completed_at;
|
|
219
|
+
let events;
|
|
220
|
+
const stopSampling = startMemorySampler((_a = props.memory) !== null && _a !== void 0 ? _a : (() => __awaiter(this, void 0, void 0, function* () { return process.memoryUsage(); })), memories);
|
|
221
|
+
try {
|
|
222
|
+
events = (yield Promise.all(servants.map((connector, index) => connector.getDriver().execute({
|
|
223
|
+
count: counts[index],
|
|
224
|
+
simultaneous: budgets[index],
|
|
225
|
+
})))).flat();
|
|
226
|
+
completed_at = new Date();
|
|
227
|
+
}
|
|
228
|
+
finally {
|
|
229
|
+
stopSampling();
|
|
230
|
+
yield closeAll(servants);
|
|
231
|
+
}
|
|
144
232
|
if (props.progress)
|
|
145
233
|
props.progress(props.count);
|
|
146
234
|
const endpoints = new tstl_1.HashMap((key) => (0, tstl_1.hash)(key.method, key.path), (x, y) => x.method === y.method && x.path === y.path);
|
|
@@ -148,15 +236,15 @@ var DynamicBenchmarker;
|
|
|
148
236
|
endpoints
|
|
149
237
|
.take({
|
|
150
238
|
method: e.metadata.method,
|
|
151
|
-
path: (
|
|
239
|
+
path: (_b = e.metadata.template) !== null && _b !== void 0 ? _b : e.metadata.path,
|
|
152
240
|
}, () => [])
|
|
153
241
|
.push(e);
|
|
154
242
|
return {
|
|
155
243
|
count: props.count,
|
|
156
244
|
threads: props.threads,
|
|
157
245
|
simultaneous: props.simultaneous,
|
|
158
|
-
statistics:
|
|
159
|
-
endpoints: [...endpoints].map((it) => (Object.assign(Object.assign({},
|
|
246
|
+
statistics: DynamicBenchmarkStatistics_1.DynamicBenchmarkStatistics.of(events),
|
|
247
|
+
endpoints: [...endpoints].map((it) => (Object.assign(Object.assign({}, DynamicBenchmarkStatistics_1.DynamicBenchmarkStatistics.of(it.second)), it.first))),
|
|
160
248
|
started_at: started_at.toISOString(),
|
|
161
249
|
completed_at: completed_at.toISOString(),
|
|
162
250
|
memories,
|
|
@@ -167,8 +255,33 @@ var DynamicBenchmarker;
|
|
|
167
255
|
*
|
|
168
256
|
* Creates a servant program executing the prefixed functions in parallel.
|
|
169
257
|
*
|
|
258
|
+
* Processing cost: Each execute request discovers matching modules once, then
|
|
259
|
+
* runs at most simultaneous loop workers and count invocations. Event storage
|
|
260
|
+
* grows with actual logger calls rather than an assumed one event per
|
|
261
|
+
* invocation.
|
|
262
|
+
*
|
|
263
|
+
* Computation reuse: Discovery is refreshed for each execute request because
|
|
264
|
+
* the supplied filter and filesystem can change; requests themselves are
|
|
265
|
+
* effectful and cannot reuse earlier observations.
|
|
266
|
+
*
|
|
267
|
+
* Resource ownership: The returned WorkerServer transfers connection
|
|
268
|
+
* lifecycle to its caller. Each execute owns its discovery collections,
|
|
269
|
+
* workers and event arrays until it completes; the master closes its servant
|
|
270
|
+
* process. No discovered-module cache is retained by this namespace beyond
|
|
271
|
+
* Node own loader.
|
|
272
|
+
*
|
|
273
|
+
* Platform boundary: WorkerConnector process mode owns Node child-process
|
|
274
|
+
* launch/IPC and its explicit stdio modes. Feature discovery resolves the
|
|
275
|
+
* caller location with native path and fs realpath/stat, follows directory
|
|
276
|
+
* links with realpath cycle detection and imports discovered native absolute
|
|
277
|
+
* paths. It does not infer filesystem case policy from OS names.
|
|
278
|
+
*
|
|
170
279
|
* @param props Properties of the servant program
|
|
171
280
|
* @returns Servant program as a worker server
|
|
281
|
+
* @evidence contracts/common.md#principled-implementation A servant opens a `WorkerServer` that exposes one `execute` operation; the master decides counts and budgets, so the servant only needs the location and naming rules to find functions.
|
|
282
|
+
* @evidence contracts/common.md#clear-and-simple-design A thin adapter over the worker server whose behavior lives in the private `execute` and `iterate` helpers.
|
|
283
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts Discovery is driven by the caller's location, extension, and prefix, and by the master's filter; no file or function name is assumed.
|
|
284
|
+
* @evidence contracts/common.md#meaningful-documentation The comment states that it creates the servant program and returns it as a worker server.
|
|
172
285
|
*/
|
|
173
286
|
DynamicBenchmarker.servant = (props) => __awaiter(this, void 0, void 0, function* () {
|
|
174
287
|
const server = new tgrid_1.WorkerServer();
|
|
@@ -183,19 +296,36 @@ var DynamicBenchmarker;
|
|
|
183
296
|
/**
|
|
184
297
|
* Convert the benchmark report to markdown content.
|
|
185
298
|
*
|
|
299
|
+
* Processing cost: Rendering delegates to the reporter and scales with report
|
|
300
|
+
* endpoints, samples and output bytes; host metadata is obtained through Node
|
|
301
|
+
* os APIs.
|
|
302
|
+
*
|
|
303
|
+
* Platform boundary: The wrapper obtains host information through Node os
|
|
304
|
+
* APIs and passes those facts to the pure renderer without constructing
|
|
305
|
+
* native file paths or shell commands.
|
|
306
|
+
*
|
|
186
307
|
* @param report Benchmark report
|
|
187
308
|
* @returns Markdown content
|
|
309
|
+
* @evidence contracts/common.md#principled-implementation Rendering is a pure function of the report and a few host facts, delegated to the reporter so the report type and its presentation stay separate.
|
|
310
|
+
* @evidence contracts/common.md#clear-and-simple-design The wrapper captures three native host facts and delegates rendering, giving users one entry point without exposing the internal reporter.
|
|
311
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts The function observes native host facts and formats the report without altering its measurements.
|
|
312
|
+
* @evidence contracts/common.md#meaningful-documentation The comment states input and output: a report in, markdown content out.
|
|
188
313
|
*/
|
|
189
|
-
DynamicBenchmarker.markdown = (report) => DynamicBenchmarkReporter_1.DynamicBenchmarkReporter.markdown(report
|
|
314
|
+
DynamicBenchmarker.markdown = (report) => { var _a; return DynamicBenchmarkReporter_1.DynamicBenchmarkReporter.markdown(report, {
|
|
315
|
+
cpu: (_a = os_1.default.cpus()[0]) === null || _a === void 0 ? void 0 : _a.model,
|
|
316
|
+
memory: os_1.default.totalmem(),
|
|
317
|
+
node: process.version,
|
|
318
|
+
}); };
|
|
190
319
|
const execute = (ctx) => (mass) => __awaiter(this, void 0, void 0, function* () {
|
|
191
320
|
const functions = [];
|
|
192
321
|
yield iterate({
|
|
193
322
|
collection: functions,
|
|
194
323
|
driver: ctx.driver,
|
|
195
324
|
props: ctx.props,
|
|
196
|
-
})(ctx.props.location);
|
|
325
|
+
})(path_1.default.resolve(ctx.props.location));
|
|
197
326
|
const entireEvents = [];
|
|
198
327
|
let scheduled = 0;
|
|
328
|
+
let completed = 0;
|
|
199
329
|
yield Promise.all(new Array(mass.simultaneous)
|
|
200
330
|
.fill(null)
|
|
201
331
|
.map(() => 1)
|
|
@@ -225,29 +355,84 @@ var DynamicBenchmarker;
|
|
|
225
355
|
for (const e of localEvents)
|
|
226
356
|
e.success = false;
|
|
227
357
|
}
|
|
228
|
-
|
|
229
|
-
ctx.driver.progress(entireEvents.length).catch(() => { });
|
|
358
|
+
ctx.driver.progress(++completed).catch(() => { });
|
|
230
359
|
}
|
|
231
360
|
})));
|
|
232
|
-
yield ctx.driver.progress(
|
|
361
|
+
yield ctx.driver.progress(completed);
|
|
233
362
|
return entireEvents;
|
|
234
363
|
});
|
|
235
364
|
})(DynamicBenchmarker || (exports.DynamicBenchmarker = DynamicBenchmarker = {}));
|
|
236
|
-
|
|
365
|
+
/**
|
|
366
|
+
* Keeps the sampler's pending caller task separate from the master's report,
|
|
367
|
+
* connectors and events. Stopping detaches the report array immediately;
|
|
368
|
+
* cancellation of a caller-owned getter remains its caller's responsibility.
|
|
369
|
+
*/
|
|
370
|
+
const startMemorySampler = (getter, memories) => {
|
|
371
|
+
const state = {
|
|
372
|
+
active: true,
|
|
373
|
+
target: memories,
|
|
374
|
+
};
|
|
375
|
+
sampleMemory(getter, state).catch(() => { });
|
|
376
|
+
return () => stopMemorySampler(state);
|
|
377
|
+
};
|
|
378
|
+
const stopMemorySampler = (state) => {
|
|
379
|
+
state.active = false;
|
|
380
|
+
state.target = null;
|
|
381
|
+
if (state.timer !== undefined)
|
|
382
|
+
clearTimeout(state.timer);
|
|
383
|
+
state.timer = undefined;
|
|
384
|
+
const wake = state.wake;
|
|
385
|
+
state.wake = undefined;
|
|
386
|
+
wake === null || wake === void 0 ? void 0 : wake();
|
|
387
|
+
};
|
|
388
|
+
const sampleMemory = (getter, state) => __awaiter(void 0, void 0, void 0, function* () {
|
|
389
|
+
try {
|
|
390
|
+
while (state.active) {
|
|
391
|
+
yield new Promise((resolve) => {
|
|
392
|
+
state.wake = resolve;
|
|
393
|
+
state.timer = setTimeout(() => {
|
|
394
|
+
state.timer = undefined;
|
|
395
|
+
state.wake = undefined;
|
|
396
|
+
resolve();
|
|
397
|
+
}, 1000);
|
|
398
|
+
});
|
|
399
|
+
if (!state.active)
|
|
400
|
+
return;
|
|
401
|
+
const usage = yield getter();
|
|
402
|
+
if (!state.active)
|
|
403
|
+
return;
|
|
404
|
+
state.target.push({ usage, time: new Date().toISOString() });
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
finally {
|
|
408
|
+
stopMemorySampler(state);
|
|
409
|
+
}
|
|
410
|
+
});
|
|
411
|
+
// A servant that fails to close cannot change a finished report, and must not
|
|
412
|
+
// hide the error that ended the run, so a failed close is dropped.
|
|
413
|
+
const closeAll = (servants) => __awaiter(void 0, void 0, void 0, function* () {
|
|
414
|
+
yield Promise.allSettled(servants.map((connector) => connector.close()));
|
|
415
|
+
});
|
|
416
|
+
const iterate = (ctx) => (path_2, ...args_1) => __awaiter(void 0, [path_2, ...args_1], void 0, function* (path, visited = new Set()) {
|
|
237
417
|
var _a;
|
|
418
|
+
const identity = yield fs_1.default.promises.realpath(path);
|
|
419
|
+
if (visited.has(identity))
|
|
420
|
+
return;
|
|
421
|
+
visited.add(identity);
|
|
238
422
|
const directory = yield fs_1.default.promises.readdir(path);
|
|
239
423
|
for (const file of directory) {
|
|
240
424
|
const location = `${path}/${file}`;
|
|
241
425
|
const stat = yield fs_1.default.promises.stat(location);
|
|
242
426
|
if (stat.isDirectory() === true)
|
|
243
|
-
yield iterate(ctx)(location);
|
|
427
|
+
yield iterate(ctx)(location, visited);
|
|
244
428
|
// Load feature files whose extension matches `props.extension`. This is
|
|
245
429
|
// configurable instead of inferred from the servant's own module
|
|
246
430
|
// extension, because the benchmark library may be built (`.js`) while the
|
|
247
431
|
// feature files it drives are run from source (`.ts`, e.g. under `ttsx`);
|
|
248
432
|
// inferring would look for `.js` features that do not exist, load
|
|
249
433
|
// nothing, and spin forever.
|
|
250
|
-
else if (
|
|
434
|
+
else if (stat.isFile() &&
|
|
435
|
+
file.endsWith(`.${(_a = ctx.props.extension) !== null && _a !== void 0 ? _a : "js"}`) &&
|
|
251
436
|
file.endsWith(".d.ts") === false) {
|
|
252
437
|
// GATE BY FILE NAME (PREFIX & FILTER), SO THAT EXCLUDED FILES ARE
|
|
253
438
|
// NEVER IMPORTED.
|
|
@@ -269,32 +454,4 @@ const iterate = (ctx) => (path) => __awaiter(void 0, void 0, void 0, function* (
|
|
|
269
454
|
}
|
|
270
455
|
}
|
|
271
456
|
});
|
|
272
|
-
const statistics = (events) => {
|
|
273
|
-
const successes = events.filter((event) => event.success);
|
|
274
|
-
return Object.assign({ count: events.length, success: successes.length }, average(events));
|
|
275
|
-
};
|
|
276
|
-
const average = (events) => {
|
|
277
|
-
if (events.length === 0)
|
|
278
|
-
return {
|
|
279
|
-
mean: null,
|
|
280
|
-
stdev: null,
|
|
281
|
-
minimum: null,
|
|
282
|
-
maximum: null,
|
|
283
|
-
};
|
|
284
|
-
let mean = 0;
|
|
285
|
-
let stdev = 0;
|
|
286
|
-
let minimum = Number.MAX_SAFE_INTEGER;
|
|
287
|
-
let maximum = Number.MIN_SAFE_INTEGER;
|
|
288
|
-
for (const event of events) {
|
|
289
|
-
const elapsed = new Date(event.completed_at).getTime() -
|
|
290
|
-
new Date(event.started_at).getTime();
|
|
291
|
-
mean += elapsed;
|
|
292
|
-
stdev += elapsed * elapsed;
|
|
293
|
-
minimum = Math.min(minimum, elapsed);
|
|
294
|
-
maximum = Math.max(maximum, elapsed);
|
|
295
|
-
}
|
|
296
|
-
mean /= events.length;
|
|
297
|
-
stdev = Math.sqrt(stdev / events.length - mean * mean);
|
|
298
|
-
return { mean, stdev, minimum, maximum };
|
|
299
|
-
};
|
|
300
457
|
//# sourceMappingURL=DynamicBenchmarker.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DynamicBenchmarker.js","sourceRoot":"","sources":["../src/DynamicBenchmarker.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,4CAAoB;AACpB,iCAA8D;AAC9D,+
|
|
1
|
+
{"version":3,"file":"DynamicBenchmarker.js","sourceRoot":"","sources":["../src/DynamicBenchmarker.ts"],"names":[],"mappings":"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"}
|
package/lib/IBenchmarkEvent.d.ts
CHANGED
|
@@ -1,9 +1,28 @@
|
|
|
1
1
|
import { IFetchRoute } from "@nestia/fetcher";
|
|
2
|
+
/**
|
|
3
|
+
* One benchmarked request as the servant observed it.
|
|
4
|
+
*
|
|
5
|
+
* `metadata` is the fetch route, `status` is the HTTP status or `null` when
|
|
6
|
+
* there was no response, and the three timestamps are ISO 8601 strings, with
|
|
7
|
+
* `respond_at` `null` when no response arrived. `success` is `false` for every
|
|
8
|
+
* request made by a benchmark function that threw.
|
|
9
|
+
*
|
|
10
|
+
* @evidence contracts/common.md#principled-implementation The event mirrors the fetcher's log event with timestamps in ISO strings, so it can cross the process boundary as plain data.
|
|
11
|
+
* @evidence contracts/common.md#clear-and-simple-design A flat record shared by the servant, the master, and the report code.
|
|
12
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts Route, status and times come from the fetcher's event; success records whether the enclosing benchmark function threw, independent of HTTP status.
|
|
13
|
+
* @evidence contracts/common.md#meaningful-documentation The comment states each optional state and the meaning of success.
|
|
14
|
+
*/
|
|
2
15
|
export interface IBenchmarkEvent {
|
|
16
|
+
/** Fetch route, including its concrete path and optional grouping template. */
|
|
3
17
|
metadata: IFetchRoute<any>;
|
|
18
|
+
/** HTTP status, or null when the request received no response. */
|
|
4
19
|
status: number | null;
|
|
20
|
+
/** ISO 8601 time when the request started. */
|
|
5
21
|
started_at: string;
|
|
22
|
+
/** ISO 8601 response time, or null when no response arrived. */
|
|
6
23
|
respond_at: string | null;
|
|
24
|
+
/** ISO 8601 time when the request completed or failed. */
|
|
7
25
|
completed_at: string;
|
|
26
|
+
/** Whether the enclosing benchmark function completed without throwing. */
|
|
8
27
|
success: boolean;
|
|
9
28
|
}
|
|
@@ -1,4 +1,53 @@
|
|
|
1
1
|
import { DynamicBenchmarker } from "../DynamicBenchmarker";
|
|
2
|
+
/**
|
|
3
|
+
* Renders a benchmark report as markdown.
|
|
4
|
+
*
|
|
5
|
+
* @evidence contracts/common.md#principled-implementation The reporter formats one report into fixed sections (specifications, arguments, time, statistics, memory chart, endpoints, failures) using a fixed locale.
|
|
6
|
+
* @evidence contracts/common.md#clear-and-simple-design A one-function namespace, internal to the package, that keeps presentation out of the benchmark logic.
|
|
7
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts The content is computed from the report and host facts; no numbers are hardcoded.
|
|
8
|
+
* @evidence contracts/common.md#meaningful-documentation The comment states its single job.
|
|
9
|
+
*/
|
|
2
10
|
export declare namespace DynamicBenchmarkReporter {
|
|
3
|
-
|
|
11
|
+
/**
|
|
12
|
+
* Host facts captured by the caller when a report is rendered.
|
|
13
|
+
*
|
|
14
|
+
* An absent CPU model means the platform exposed no CPU information. Memory
|
|
15
|
+
* remains in bytes until rendering, and the Node version is displayed
|
|
16
|
+
* verbatim.
|
|
17
|
+
*
|
|
18
|
+
* Platform boundary: Missing CPU data is represented explicitly rather than
|
|
19
|
+
* inferred from an operating-system name; memory and version retain Node's
|
|
20
|
+
* native units and spelling.
|
|
21
|
+
*
|
|
22
|
+
* @evidence contracts/common.md#principled-implementation CPU absence, memory bytes and the runtime version represent the three facts displayed by the renderer without depending on a platform-specific provider.
|
|
23
|
+
* @evidence contracts/common.md#clear-and-simple-design One record separates host observation from report formatting; each member supplies one displayed fact.
|
|
24
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts The record describes native facts supplied by the actual public caller and introduces no fixture-specific behavior.
|
|
25
|
+
* @evidence contracts/common.md#meaningful-documentation Member comments explain absence, units and display semantics.
|
|
26
|
+
*/
|
|
27
|
+
interface IHost {
|
|
28
|
+
/** First CPU model, or undefined when the platform reports no CPU. */
|
|
29
|
+
cpu: string | undefined;
|
|
30
|
+
/** Total host memory in bytes. */
|
|
31
|
+
memory: number;
|
|
32
|
+
/** Node runtime version as reported by process.version. */
|
|
33
|
+
node: string;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Renders the report as markdown.
|
|
37
|
+
*
|
|
38
|
+
* Numbers use the fixed `en-US` locale, so a report reads the same on every
|
|
39
|
+
* machine. Decimals are truncated, not rounded, to two places. The CPU model
|
|
40
|
+
* is `unknown` when the platform exposes no CPU information.
|
|
41
|
+
*
|
|
42
|
+
* Processing cost: Endpoint and failure ordering require comparison sorts,
|
|
43
|
+
* costing O(E log E); four memory series each scan M samples, and temporary
|
|
44
|
+
* rows and final text scale with displayed data. Sorting copies preserve the
|
|
45
|
+
* caller's endpoint order.
|
|
46
|
+
*
|
|
47
|
+
* @evidence contracts/common.md#principled-implementation Each table row is built from the same statistics record; `Math.trunc` on the value scaled by 100 truncates toward zero to two decimals, including negative elapsed values after a wall-clock adjustment. `en-US` fixes separators, and an absent CPU model is displayed as `unknown`.
|
|
48
|
+
* @evidence contracts/common.md#clear-and-simple-design Small local helpers (`integer`, `format`, `row`, `line`) share the formatting rules inside one function, so one place decides how a number reads.
|
|
49
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts The report states only the report's measurements and supplied host facts; nothing describes an unmeasured backend server or changes foreign runtime methods.
|
|
50
|
+
* @evidence contracts/common.md#meaningful-documentation The comment states the locale, the truncation, and the CPU fallback.
|
|
51
|
+
*/
|
|
52
|
+
const markdown: (report: DynamicBenchmarker.IReport, host: IHost) => string;
|
|
4
53
|
}
|