@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 CHANGED
@@ -60,7 +60,7 @@ Check out the document in the [website](https://nestia.io/docs/):
60
60
  ### 🏠 Home
61
61
  - [Introduction](https://nestia.io/docs/)
62
62
  - [Setup](https://nestia.io/docs/setup/)
63
- - [Pure TypeScript](https://nestia.io/docs/pure)
63
+ - [Pure TypeScript](https://nestia.io/docs/core/TypedBody/)
64
64
 
65
65
  ### 📖 Features
66
66
  - Core Library
@@ -27,17 +27,65 @@ import { IBenchmarkServant } from "./internal/IBenchmarkServant";
27
27
  * Additionally, if you hope to see some utilization cases, see the below
28
28
  * example tagged links.
29
29
  *
30
+ * Processing cost: Totals are split across T servants once; E events are
31
+ * aggregated with hash-based endpoint grouping. Progress notifications update
32
+ * the aggregate from one servant counter delta in constant time. Event
33
+ * statistics and rendering traverse their input populations; discovery visits
34
+ * each real directory once.
35
+ *
36
+ * Computation reuse: A master distributes distinct request budgets rather than
37
+ * replaying one effectful request. Endpoint grouping shares one event
38
+ * population across whole-run and endpoint statistics. Results are not cached
39
+ * across benchmark runs because server state and timing change.
40
+ *
41
+ * Resource ownership: Each master owns at most threads connectors and
42
+ * simultaneous function workers; connector closure is attempted on
43
+ * connection/execution success or failure; a rejected close is suppressed and
44
+ * may leave an unreleased child process. Events retained by servants/master
45
+ * scale with logged events, and memory samples with run duration. The
46
+ * independent sampler detaches its report target on stop or rejection and
47
+ * clears/wakes its owned timer. A pending caller memory getter has no
48
+ * cancellation hook, but its task retains only the sampler state/getter and
49
+ * cannot keep the master report arrays, connectors or event collections through
50
+ * that state. Its eventual result is discarded after deactivation. Returned
51
+ * reports transfer their arrays to callers.
52
+ *
53
+ * Platform boundary: WorkerConnector process mode owns Node child-process
54
+ * launch/IPC and its explicit stdio modes. Feature discovery resolves the
55
+ * caller location with native path and fs realpath/stat, follows directory
56
+ * links with realpath cycle detection and imports discovered native absolute
57
+ * paths. It does not infer filesystem case policy from OS names.
58
+ *
30
59
  * @author Jeongho Nam - https://github.com/samchon
31
60
  * @example
32
61
  * https://github.com/samchon/nestia-start/blob/master/test/benchmaark/index.ts
33
62
  *
34
63
  * @example
35
64
  * https://github.com/samchon/backend/blob/master/test/benchmark/index.ts
65
+ *
66
+ * @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.
67
+ * @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.
68
+ * @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.
69
+ * @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.
36
70
  */
37
71
  export declare namespace DynamicBenchmarker {
38
- /** Properties of the master program. */
72
+ /**
73
+ * Properties of the master program.
74
+ *
75
+ * Platform boundary: The servant path uses native filesystem spelling, and
76
+ * stdio exposes Node child-process modes without imposing separator or case
77
+ * policy.
78
+ *
79
+ * @evidence contracts/common.md#principled-implementation The fields are exactly what the master needs to plan a run: totals, parallelism, how to reach the servant program, and optional hooks; the count, threads, and simultaneous constraints are enforced by `master`, which the field prose states.
80
+ * @evidence contracts/common.md#clear-and-simple-design A flat property record; optional members carry the only extension points (filter, progress, memory, stdio).
81
+ * @evidence contracts/common.md#prohibited-implementation-shortcuts Every value is caller-supplied; no default names a target application or fixture.
82
+ * @evidence contracts/common.md#meaningful-documentation Each property documents its meaning and constraints, including how simultaneous is distributed among threads and that the filter receives a file basename.
83
+ */
39
84
  interface IMasterProps {
40
- /** Total count of the requests. */
85
+ /**
86
+ * Total number of benchmark function invocations, each of which may log
87
+ * several HTTP requests.
88
+ */
41
89
  count: number;
42
90
  /**
43
91
  * Number of threads.
@@ -50,8 +98,9 @@ export declare namespace DynamicBenchmarker {
50
98
  *
51
99
  * The number of requests to be executed simultaneously.
52
100
  *
53
- * This property value would be divided by the {@link threads} in the
54
- * servants.
101
+ * This property value is distributed among the {@link threads} servants like
102
+ * the {@link count}, so their budgets sum to it. It must not be less than
103
+ * the {@link threads}, as each servant runs at least one request at a time.
55
104
  */
56
105
  simultaneous: number;
57
106
  /**
@@ -71,12 +120,23 @@ export declare namespace DynamicBenchmarker {
71
120
  *
72
121
  * @param file File name (basename) of the benchmark functions
73
122
  * @returns Whether to execute the function or not.
123
+ * @evidence contracts/common.md#principled-implementation The predicate is asked for each candidate file name through the master driver before the servant imports it, so a rejected file's functions can never execute.
124
+ * @evidence contracts/common.md#clear-and-simple-design A single predicate on the file basename, with a default that accepts everything.
125
+ * @evidence contracts/common.md#prohibited-implementation-shortcuts Selection is by the caller's predicate, not by known file names.
126
+ * @evidence contracts/common.md#meaningful-documentation The comment states the argument (basename, not function name) and that a `false` result prevents the import.
74
127
  */
75
128
  filter?: (file: string) => boolean;
76
129
  /**
77
130
  * Progress callback function.
78
131
  *
79
- * @param complete The number of completed requests.
132
+ * Progress counts completed benchmark function invocations, regardless of
133
+ * how many HTTP events each invocation logs.
134
+ *
135
+ * @param complete The number of completed benchmark function invocations.
136
+ * @evidence contracts/common.md#principled-implementation The callback receives the sum of completed invocation counts from every servant and is called once more with the requested count at the end, including when no matching functions were discovered.
137
+ * @evidence contracts/common.md#clear-and-simple-design One optional notification with a single number argument.
138
+ * @evidence contracts/common.md#prohibited-implementation-shortcuts The callback does not configure request counts or concurrency; a throw from the final callback propagates after servants have been closed rather than being hidden.
139
+ * @evidence contracts/common.md#meaningful-documentation The comment distinguishes completed benchmark function invocations from logged HTTP events.
80
140
  */
81
141
  progress?: (complete: number) => void;
82
142
  /**
@@ -87,6 +147,16 @@ export declare namespace DynamicBenchmarker {
87
147
  * Specify this property only when your backend server is running on a
88
148
  * different process, so that need to measure the memory usage of the
89
149
  * backend server from other process.
150
+ *
151
+ * The function is called once a second while the benchmark runs. If it
152
+ * rejects, the sampling stops and the report keeps the samples taken so
153
+ * far. A result still pending when execution ends is discarded when it
154
+ * settles.
155
+ *
156
+ * @evidence contracts/common.md#principled-implementation When the server under test runs in another process, the master's own `process.memoryUsage()` measures the wrong process, so the caller supplies a getter for the right one; it is sampled once a second while the run lasts.
157
+ * @evidence contracts/common.md#clear-and-simple-design One optional async getter that replaces the default sampler and nothing else.
158
+ * @evidence contracts/common.md#prohibited-implementation-shortcuts The default measures the master process itself; a caller getter is used as given, and a getter that rejects ends sampling rather than being retried or replaced.
159
+ * @evidence contracts/common.md#meaningful-documentation The comment states when to set it, the sampling cadence, and that a rejection stops the sampling and keeps earlier samples.
90
160
  */
91
161
  memory?: () => Promise<NodeJS.MemoryUsage>;
92
162
  /**
@@ -96,7 +166,18 @@ export declare namespace DynamicBenchmarker {
96
166
  */
97
167
  stdio?: undefined | "overlapped" | "pipe" | "ignore" | "inherit";
98
168
  }
99
- /** Properties of the servant program. */
169
+ /**
170
+ * Properties of the servant program.
171
+ *
172
+ * Platform boundary: The feature location and extension describe native files
173
+ * separately from the connection's protocol address; relative paths use the
174
+ * servant's working directory.
175
+ *
176
+ * @evidence contracts/common.md#principled-implementation The fields define how a servant finds benchmark functions (location, extension, prefix) and how it builds their arguments (connection and parameters), which is everything discovery and invocation need.
177
+ * @evidence contracts/common.md#clear-and-simple-design A generic property record parameterized by the tuple of function arguments, with the optional extension defaulting to the built JavaScript.
178
+ * @evidence contracts/common.md#prohibited-implementation-shortcuts The extension is declared rather than inferred from the servant's own module, which once loaded no feature at all when the library was built and the features ran from TypeScript source.
179
+ * @evidence contracts/common.md#meaningful-documentation Each property documents its role, the default extension, the file-name and function-name prefix rules, and what happens when nothing matches.
180
+ */
100
181
  interface IServantProps<Parameters extends any[]> {
101
182
  /**
102
183
  * Default connection.
@@ -104,7 +185,12 @@ export declare namespace DynamicBenchmarker {
104
185
  * Default connection to be used in the servant.
105
186
  */
106
187
  connection: IConnection;
107
- /** Location of the benchmark functions. */
188
+ /**
189
+ * Location of the benchmark functions.
190
+ *
191
+ * A relative path is resolved against the current working directory of the
192
+ * servant, the same base that lists the directory.
193
+ */
108
194
  location: string;
109
195
  /**
110
196
  * Extension of the benchmark function files to load, without the leading
@@ -127,6 +213,9 @@ export declare namespace DynamicBenchmarker {
127
213
  * would never be executed. Also, when a file name (basename) does not start
128
214
  * with the prefix, the file would never be imported either, so that every
129
215
  * function defined in the file would never be executed.
216
+ *
217
+ * When no function matches, no request is executed and the report carries
218
+ * no events.
130
219
  */
131
220
  prefix: string;
132
221
  /**
@@ -138,35 +227,102 @@ export declare namespace DynamicBenchmarker {
138
227
  *
139
228
  * @param connection Default connection instance
140
229
  * @param name Function name
230
+ * @evidence contracts/common.md#principled-implementation A function from the per-request connection and the function name to the argument tuple lets each execution receive a connection whose logger records its events.
231
+ * @evidence contracts/common.md#clear-and-simple-design One callback, called per execution, with the two inputs a caller needs to build arguments.
232
+ * @evidence contracts/common.md#prohibited-implementation-shortcuts Arguments come only from the caller's function; the connection it receives is the servant's logging copy.
233
+ * @evidence contracts/common.md#meaningful-documentation The comment warns that the logger of the received connection must be carried into the returned parameters, the fact that decides whether events are recorded.
141
234
  */
142
235
  parameters: (connection: IConnection, name: string) => Parameters;
143
236
  }
144
- /** Benchmark report. */
237
+ /**
238
+ * Benchmark report.
239
+ *
240
+ * Times are ISO 8601 strings, durations are milliseconds, and the
241
+ * {@link statistics} and every entry of {@link endpoints} describe the same
242
+ * collected events, grouped by method and path template.
243
+ *
244
+ * @evidence contracts/common.md#principled-implementation The report is the master's merged observation: the run parameters, whole-run statistics, per-endpoint statistics, and memory samples, all derived from one event collection.
245
+ * @evidence contracts/common.md#clear-and-simple-design A flat record whose nested types (`IEndpoint`, `IStatistics`, `IMemory`) name the parts, with no behavior.
246
+ * @evidence contracts/common.md#prohibited-implementation-shortcuts Every field is measured or copied from the request; none is a fixture value.
247
+ * @evidence contracts/common.md#meaningful-documentation The prose states the time format, the duration unit, and how statistics and endpoints relate.
248
+ */
145
249
  interface IReport {
250
+ /** Requested number of benchmark function invocations. */
146
251
  count: number;
252
+ /** Number of servant processes requested. */
147
253
  threads: number;
254
+ /** Aggregate limit on concurrent benchmark function invocations. */
148
255
  simultaneous: number;
256
+ /** ISO 8601 time when connected servants started executing. */
149
257
  started_at: string;
258
+ /** ISO 8601 time when every servant finished executing. */
150
259
  completed_at: string;
260
+ /** Statistics over all HTTP events logged by the benchmark functions. */
151
261
  statistics: IReport.IStatistics;
262
+ /** The same events grouped by HTTP method and route path template. */
152
263
  endpoints: Array<IReport.IEndpoint & IReport.IStatistics>;
264
+ /**
265
+ * Memory samples obtained during execution; failed or pending readings are
266
+ * omitted.
267
+ */
153
268
  memories: IReport.IMemory[];
154
269
  }
155
270
  namespace IReport {
271
+ /**
272
+ * Identity of an endpoint in the report: the HTTP method and the route
273
+ * path, using the path template when the route declares one.
274
+ *
275
+ * @evidence contracts/common.md#principled-implementation An endpoint is identified by method and path, the pair the master groups events by, with the template preferred so parameterized paths aggregate.
276
+ * @evidence contracts/common.md#clear-and-simple-design Two string fields with no behavior.
277
+ * @evidence contracts/common.md#prohibited-implementation-shortcuts Grouping uses the route metadata carried by each event, without a list of known endpoints.
278
+ * @evidence contracts/common.md#meaningful-documentation The comment states which path form is used for grouping.
279
+ */
156
280
  interface IEndpoint {
281
+ /** HTTP method of the grouped requests. */
157
282
  method: string;
283
+ /** Route template, falling back to the concrete route path. */
158
284
  path: string;
159
285
  }
286
+ /**
287
+ * Statistics of a set of benchmarked requests.
288
+ *
289
+ * Durations are milliseconds from the request start to its completion.
290
+ * `mean`, `stdev`, `minimum`, and `maximum` are `null` when there are no
291
+ * events, and `stdev` is the population standard deviation. `success`
292
+ * counts the events whose executed function did not throw.
293
+ *
294
+ * @evidence contracts/common.md#principled-implementation Counts are exact, the mean and population standard deviation are computed over the same set, and `null` marks the empty set where no value is defined.
295
+ * @evidence contracts/common.md#clear-and-simple-design A flat record of six measures reused for the whole run and for each endpoint.
296
+ * @evidence contracts/common.md#prohibited-implementation-shortcuts The values are computed from the events; no measure is defaulted to a plausible number.
297
+ * @evidence contracts/common.md#meaningful-documentation The comment states the unit, the empty-set convention, the deviation kind, and what success counts.
298
+ */
160
299
  interface IStatistics {
300
+ /** Number of logged HTTP events. */
161
301
  count: number;
302
+ /** Events whose enclosing benchmark function completed without throwing. */
162
303
  success: number;
304
+ /** Mean duration in milliseconds, or null for no events. */
163
305
  mean: number | null;
306
+ /** Population standard deviation in milliseconds, or null for no events. */
164
307
  stdev: number | null;
308
+ /** Shortest duration in milliseconds, or null for no events. */
165
309
  minimum: number | null;
310
+ /** Longest duration in milliseconds, or null for no events. */
166
311
  maximum: number | null;
167
312
  }
313
+ /**
314
+ * One memory sample taken while the benchmark ran: an ISO 8601 time and the
315
+ * process memory usage read by the sampler.
316
+ *
317
+ * @evidence contracts/common.md#principled-implementation A sample pairs the instant with the usage object exactly as the getter returned it, so the report keeps Node's own fields.
318
+ * @evidence contracts/common.md#clear-and-simple-design Two fields with no behavior.
319
+ * @evidence contracts/common.md#prohibited-implementation-shortcuts The usage is the getter's return value, not a synthesized reading.
320
+ * @evidence contracts/common.md#meaningful-documentation The comment states the time format and the source of the usage.
321
+ */
168
322
  interface IMemory {
323
+ /** ISO 8601 time when the memory getter completed. */
169
324
  time: string;
325
+ /** Node memory usage fields in bytes, supplied by the selected getter. */
170
326
  usage: NodeJS.MemoryUsage;
171
327
  }
172
328
  }
@@ -178,8 +334,45 @@ export declare namespace DynamicBenchmarker {
178
334
  * Note that, {@link IMasterProps.servant} property must be the path of the
179
335
  * servant program executing the {@link servant} function.
180
336
  *
337
+ * The servants are child processes. When a servant fails to connect or to
338
+ * execute, every servant receives a close attempt before the returned promise
339
+ * rejects.
340
+ *
341
+ * Processing cost: Totals are split across T servants once; E events are
342
+ * aggregated with hash-based endpoint grouping. Progress notifications update
343
+ * the aggregate from one servant counter delta in constant time. Event
344
+ * statistics and rendering traverse their input populations; discovery visits
345
+ * each real directory once.
346
+ *
347
+ * Computation reuse: A master distributes distinct request budgets rather
348
+ * than replaying one effectful request. Endpoint grouping shares one event
349
+ * population across whole-run and endpoint statistics. Results are not cached
350
+ * across benchmark runs because server state and timing change.
351
+ *
352
+ * Resource ownership: Each master owns at most threads connectors and
353
+ * simultaneous function workers; connector closure is attempted on
354
+ * connection/execution success or failure; a rejected close is suppressed and
355
+ * may leave an unreleased child process. Events retained by servants/master
356
+ * scale with logged events, and memory samples with run duration. The
357
+ * independent sampler detaches its report target on stop or rejection and
358
+ * clears/wakes its owned timer. A pending caller memory getter has no
359
+ * cancellation hook, but its task retains only the sampler state/getter and
360
+ * cannot keep the master report arrays, connectors or event collections
361
+ * through that state. Its eventual result is discarded after deactivation.
362
+ * Returned reports transfer their arrays to callers.
363
+ *
364
+ * Platform boundary: WorkerConnector process mode owns Node child-process
365
+ * launch/IPC and its explicit stdio modes. Feature discovery resolves the
366
+ * caller location with native path and fs realpath/stat, follows directory
367
+ * links with realpath cycle detection and imports discovered native absolute
368
+ * paths. It does not infer filesystem case policy from OS names.
369
+ *
181
370
  * @param props Properties of the master program
182
371
  * @returns Benchmark report
372
+ * @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.
373
+ * @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.
374
+ * @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.
375
+ * @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.
183
376
  */
184
377
  const master: (props: IMasterProps) => Promise<IReport>;
185
378
  /**
@@ -187,15 +380,52 @@ export declare namespace DynamicBenchmarker {
187
380
  *
188
381
  * Creates a servant program executing the prefixed functions in parallel.
189
382
  *
383
+ * Processing cost: Each execute request discovers matching modules once, then
384
+ * runs at most simultaneous loop workers and count invocations. Event storage
385
+ * grows with actual logger calls rather than an assumed one event per
386
+ * invocation.
387
+ *
388
+ * Computation reuse: Discovery is refreshed for each execute request because
389
+ * the supplied filter and filesystem can change; requests themselves are
390
+ * effectful and cannot reuse earlier observations.
391
+ *
392
+ * Resource ownership: The returned WorkerServer transfers connection
393
+ * lifecycle to its caller. Each execute owns its discovery collections,
394
+ * workers and event arrays until it completes; the master closes its servant
395
+ * process. No discovered-module cache is retained by this namespace beyond
396
+ * Node own loader.
397
+ *
398
+ * Platform boundary: WorkerConnector process mode owns Node child-process
399
+ * launch/IPC and its explicit stdio modes. Feature discovery resolves the
400
+ * caller location with native path and fs realpath/stat, follows directory
401
+ * links with realpath cycle detection and imports discovered native absolute
402
+ * paths. It does not infer filesystem case policy from OS names.
403
+ *
190
404
  * @param props Properties of the servant program
191
405
  * @returns Servant program as a worker server
406
+ * @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.
407
+ * @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.
408
+ * @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.
409
+ * @evidence contracts/common.md#meaningful-documentation The comment states that it creates the servant program and returns it as a worker server.
192
410
  */
193
411
  const servant: <Parameters extends any[]>(props: IServantProps<Parameters>) => Promise<WorkerServer<null, IBenchmarkServant, IBenchmarkMaster>>;
194
412
  /**
195
413
  * Convert the benchmark report to markdown content.
196
414
  *
415
+ * Processing cost: Rendering delegates to the reporter and scales with report
416
+ * endpoints, samples and output bytes; host metadata is obtained through Node
417
+ * os APIs.
418
+ *
419
+ * Platform boundary: The wrapper obtains host information through Node os
420
+ * APIs and passes those facts to the pure renderer without constructing
421
+ * native file paths or shell commands.
422
+ *
197
423
  * @param report Benchmark report
198
424
  * @returns Markdown content
425
+ * @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.
426
+ * @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.
427
+ * @evidence contracts/common.md#prohibited-implementation-shortcuts The function observes native host facts and formats the report without altering its measurements.
428
+ * @evidence contracts/common.md#meaningful-documentation The comment states input and output: a report in, markdown content out.
199
429
  */
200
430
  const markdown: (report: DynamicBenchmarker.IReport) => string;
201
431
  }