@nadrif/thread 0.1.0
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/LICENSE +21 -0
- package/README.md +1156 -0
- package/package.json +133 -0
- package/src/adapters.js +404 -0
- package/src/config/adapters.js +188 -0
- package/src/config/define.js +171 -0
- package/src/config/env.js +218 -0
- package/src/config/frameworks.js +268 -0
- package/src/config/index.js +256 -0
- package/src/config/schema.js +375 -0
- package/src/config.js +52 -0
- package/src/deno.js +29 -0
- package/src/edge.js +38 -0
- package/src/env.js +361 -0
- package/src/error.js +340 -0
- package/src/factory.js +591 -0
- package/src/gpu/adapters.js +227 -0
- package/src/gpu/chains.js +261 -0
- package/src/gpu/env.js +372 -0
- package/src/gpu/gpu.js +1199 -0
- package/src/gpu/helpers.js +240 -0
- package/src/gpu/hooks.js +284 -0
- package/src/gpu/index.js +16 -0
- package/src/gpu/shaders.js +834 -0
- package/src/gpu/special.js +493 -0
- package/src/hooks.js +448 -0
- package/src/index.js +557 -0
- package/src/metrix.js +222 -0
- package/src/node.js +36 -0
- package/src/pool.js +740 -0
- package/src/serializer.js +139 -0
- package/src/thread.js +1246 -0
- package/src/types.js +1354 -0
- package/src/worker-factory.js +347 -0
package/src/metrix.js
ADDED
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Lightweight performance counter for threads and pools.
|
|
3
|
+
*
|
|
4
|
+
* `Metrics` tracks cumulative statistics about task execution – counts,
|
|
5
|
+
* error rates, duration distributions, and throughput. Every thread and
|
|
6
|
+
* pool maintain an internal `Metrics` instance that is updated
|
|
7
|
+
* automatically after each task.
|
|
8
|
+
*
|
|
9
|
+
* **Design note:** Error recordings (where `success = false`) increment
|
|
10
|
+
* the counter and error tally but do **not** affect `avg`, `min`, `max`,
|
|
11
|
+
* or `throughput`. This keeps the timing statistics meaningful – a
|
|
12
|
+
* crashed task that took 0 ms should not pull the average down.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```js
|
|
16
|
+
* import { Metrics } from './metrix.js';
|
|
17
|
+
*
|
|
18
|
+
* const m = new Metrics();
|
|
19
|
+
*
|
|
20
|
+
* m.record(120, true); // successful task, 120ms
|
|
21
|
+
* m.record(85, true); // successful task, 85ms
|
|
22
|
+
* m.record(0, false); // failed task
|
|
23
|
+
*
|
|
24
|
+
* const snap = m.snapshot();
|
|
25
|
+
* console.log(snap);
|
|
26
|
+
* // {
|
|
27
|
+
* // count: 3, ← total tasks (success + error)
|
|
28
|
+
* // errors: 1, ← failed tasks
|
|
29
|
+
* // avg: 102.5, ← (120+85)/2 – only successes
|
|
30
|
+
* // min: 85, ← fastest success
|
|
31
|
+
* // max: 120, ← slowest success
|
|
32
|
+
* // throughput: 9.76 ← ~9.76 tasks/sec (only successes)
|
|
33
|
+
* // errorRate: 0.33 ← 33% error rate
|
|
34
|
+
* // }
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* @module metrix
|
|
38
|
+
*/
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Tracks performance metrics for a thread or pool.
|
|
42
|
+
*
|
|
43
|
+
* Instances are lightweight – no timers, no async work. They simply
|
|
44
|
+
* accumulate data that you can query at any time via getters or
|
|
45
|
+
* {@link Metrics.snapshot}.
|
|
46
|
+
*/
|
|
47
|
+
export class Metrics {
|
|
48
|
+
/** Create an empty metrics tracker. */
|
|
49
|
+
constructor() {
|
|
50
|
+
/** @type {number} Total tasks recorded (success + error). */
|
|
51
|
+
this._count = 0;
|
|
52
|
+
/** @type {number} Successful tasks recorded. */
|
|
53
|
+
this._successCount = 0;
|
|
54
|
+
/** @type {number} Failed tasks recorded. */
|
|
55
|
+
this._errors = 0;
|
|
56
|
+
/** @type {number} Cumulative duration of successful tasks (ms). */
|
|
57
|
+
this._totalTime = 0;
|
|
58
|
+
/** @type {number} Shortest successful task (ms). */
|
|
59
|
+
this._min = Infinity;
|
|
60
|
+
/** @type {number} Longest successful task (ms). */
|
|
61
|
+
this._max = -Infinity;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// -----------------------------------------------------------------------
|
|
65
|
+
// Recording
|
|
66
|
+
// -----------------------------------------------------------------------
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Record a single task execution.
|
|
70
|
+
*
|
|
71
|
+
* Call this once per completed (or failed) task. Successful tasks
|
|
72
|
+
* update duration stats (`avg`, `min`, `max`, `throughput`); failed
|
|
73
|
+
* tasks only increment the error counter.
|
|
74
|
+
*
|
|
75
|
+
* @param {number} duration - Wall-clock duration in **milliseconds**.
|
|
76
|
+
* For failed tasks this is typically `0` since no meaningful timing
|
|
77
|
+
* is available.
|
|
78
|
+
* @param {boolean} [success=true] - Pass `false` for failed tasks.
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* ```js
|
|
82
|
+
* const m = new Metrics();
|
|
83
|
+
* const start = performance.now();
|
|
84
|
+
* await doWork();
|
|
85
|
+
* m.record(performance.now() - start, true);
|
|
86
|
+
* ```
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* ```js
|
|
90
|
+
* // Recording a failure
|
|
91
|
+
* m.record(0, false);
|
|
92
|
+
* ```
|
|
93
|
+
*/
|
|
94
|
+
record(duration, success = true) {
|
|
95
|
+
this._count++;
|
|
96
|
+
if (!success) {
|
|
97
|
+
this._errors++;
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
this._successCount++;
|
|
101
|
+
this._totalTime += duration;
|
|
102
|
+
if (duration < this._min) this._min = duration;
|
|
103
|
+
if (duration > this._max) this._max = duration;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// -----------------------------------------------------------------------
|
|
107
|
+
// Getters
|
|
108
|
+
// -----------------------------------------------------------------------
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Average duration of **successful** tasks in milliseconds.
|
|
112
|
+
*
|
|
113
|
+
* Returns `0` when no successful tasks have been recorded.
|
|
114
|
+
*
|
|
115
|
+
* @type {number}
|
|
116
|
+
*
|
|
117
|
+
* @example
|
|
118
|
+
* ```js
|
|
119
|
+
* m.record(100, true);
|
|
120
|
+
* m.record(200, true);
|
|
121
|
+
* console.log(m.avg); // 150
|
|
122
|
+
* ```
|
|
123
|
+
*/
|
|
124
|
+
get avg() {
|
|
125
|
+
return this._successCount > 0 ? this._totalTime / this._successCount : 0;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Throughput of **successful** tasks per second.
|
|
130
|
+
*
|
|
131
|
+
* Computed as `successCount / (totalTimeMs / 1000)`. Returns `0`
|
|
132
|
+
* when no successful tasks have been recorded.
|
|
133
|
+
*
|
|
134
|
+
* @type {number}
|
|
135
|
+
*
|
|
136
|
+
* @example
|
|
137
|
+
* ```js
|
|
138
|
+
* m.record(500, true); // 500ms
|
|
139
|
+
* m.record(500, true); // 500ms → total 1s
|
|
140
|
+
* console.log(m.throughput); // 2 (tasks per second)
|
|
141
|
+
* ```
|
|
142
|
+
*/
|
|
143
|
+
get throughput() {
|
|
144
|
+
return this._successCount > 0 ? this._successCount / (this._totalTime / 1000) : 0;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Error rate as a fraction between 0 and 1.
|
|
149
|
+
*
|
|
150
|
+
* Computed as `errors / totalCount`. Returns `0` when no tasks have
|
|
151
|
+
* been recorded.
|
|
152
|
+
*
|
|
153
|
+
* @type {number}
|
|
154
|
+
*
|
|
155
|
+
* @example
|
|
156
|
+
* ```js
|
|
157
|
+
* m.record(0, false);
|
|
158
|
+
* m.record(0, false);
|
|
159
|
+
* m.record(100, true);
|
|
160
|
+
* console.log(m.errorRate); // 0.666… (2 errors out of 3 tasks)
|
|
161
|
+
* ```
|
|
162
|
+
*/
|
|
163
|
+
get errorRate() {
|
|
164
|
+
return this._count > 0 ? this._errors / this._count : 0;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// -----------------------------------------------------------------------
|
|
168
|
+
// Snapshot & reset
|
|
169
|
+
// -----------------------------------------------------------------------
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Return an immutable snapshot of all metrics as a plain object.
|
|
173
|
+
*
|
|
174
|
+
* The snapshot is a **copy** – mutating it has no effect on the
|
|
175
|
+
* tracker. `min` and `max` are `0` when no successful tasks exist
|
|
176
|
+
* (instead of `Infinity` / `-Infinity`).
|
|
177
|
+
*
|
|
178
|
+
* @returns {import('./types.js').MetricsSnapshot} Current metrics state.
|
|
179
|
+
*
|
|
180
|
+
* @example
|
|
181
|
+
* ```js
|
|
182
|
+
* const snap = thread.metrics; // calls snapshot() internally
|
|
183
|
+
* console.log(`Tasks: ${snap.count}, Avg: ${snap.avg.toFixed(1)}ms`);
|
|
184
|
+
* console.log(`Error rate: ${(snap.errorRate * 100).toFixed(1)}%`);
|
|
185
|
+
* ```
|
|
186
|
+
*/
|
|
187
|
+
snapshot() {
|
|
188
|
+
return {
|
|
189
|
+
count: this._count,
|
|
190
|
+
errors: this._errors,
|
|
191
|
+
avg: this.avg,
|
|
192
|
+
min: this._min === Infinity ? 0 : this._min,
|
|
193
|
+
max: this._max === -Infinity ? 0 : this._max,
|
|
194
|
+
throughput: this.throughput,
|
|
195
|
+
errorRate: this.errorRate,
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Reset all counters to their initial values.
|
|
201
|
+
*
|
|
202
|
+
* After calling `reset()`, the tracker is indistinguishable from a
|
|
203
|
+
* freshly constructed one.
|
|
204
|
+
*
|
|
205
|
+
* @example
|
|
206
|
+
* ```js
|
|
207
|
+
* // Reset metrics at the start of each minute
|
|
208
|
+
* setInterval(() => {
|
|
209
|
+
* console.log('Last minute:', thread.metrics);
|
|
210
|
+
* thread._metrics.reset(); // internal, but illustrates the idea
|
|
211
|
+
* }, 60_000);
|
|
212
|
+
* ```
|
|
213
|
+
*/
|
|
214
|
+
reset() {
|
|
215
|
+
this._count = 0;
|
|
216
|
+
this._successCount = 0;
|
|
217
|
+
this._errors = 0;
|
|
218
|
+
this._totalTime = 0;
|
|
219
|
+
this._min = Infinity;
|
|
220
|
+
this._max = -Infinity;
|
|
221
|
+
}
|
|
222
|
+
}
|
package/src/node.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Node.js-specific entry point for the thread library.
|
|
3
|
+
*
|
|
4
|
+
* This entry point is optimised for Node.js and Bun runtimes. It:
|
|
5
|
+
*
|
|
6
|
+
* 1. Uses `worker_threads` for Worker creation (not Blob URLs)
|
|
7
|
+
* 2. Loads config from the filesystem (`fs.readFileSync`)
|
|
8
|
+
* 3. Supports dynamic `import()` for GPU bindings
|
|
9
|
+
*
|
|
10
|
+
* **Usage:**
|
|
11
|
+
*
|
|
12
|
+
* ```js
|
|
13
|
+
* // In your Node.js project
|
|
14
|
+
* import { Thread, ThreadPool, GPUCompute } from 'thread/node';
|
|
15
|
+
* ```
|
|
16
|
+
*
|
|
17
|
+
* Or in `package.json`:
|
|
18
|
+
* ```json
|
|
19
|
+
* {
|
|
20
|
+
* "imports": {
|
|
21
|
+
* "#thread": "thread/node"
|
|
22
|
+
* }
|
|
23
|
+
* }
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* @module thread/node
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
// Re-export everything from the main entry point
|
|
30
|
+
export * from './index.js';
|
|
31
|
+
export { default } from './index.js';
|
|
32
|
+
|
|
33
|
+
// Re-export environment-specific utilities
|
|
34
|
+
export { env } from './env.js';
|
|
35
|
+
export { createWorker, terminateWorker, supportsWorkers, workerInfo } from './worker-factory.js';
|
|
36
|
+
export { gpuEnv, isGPUAvailable, requestGPUAdapter, requestGPUDevice } from './gpu/env.js';
|