stardust-parallel-js 3.0.0 → 3.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/README.md +177 -23
- package/dist/primitives/Thread/BaseThread.d.ts.map +1 -1
- package/dist/primitives/Thread/BaseThread.js +4 -3
- package/dist/primitives/Thread/BaseThread.js.map +1 -1
- package/dist/primitives/ThreadPool.js +6 -6
- package/dist/primitives/ThreadPool.js.map +1 -1
- package/dist/utils/workerFactory.d.ts +2 -5
- package/dist/utils/workerFactory.d.ts.map +1 -1
- package/dist/utils/workerFactory.js +2 -45
- package/dist/utils/workerFactory.js.map +1 -1
- package/package.json +1 -1
- package/README.ru.md +0 -309
package/README.md
CHANGED
|
@@ -9,8 +9,6 @@
|
|
|
9
9
|
[](https://bundlephobia.com/package/stardust-parallel-js)
|
|
10
10
|
[](https://github.com/b1411/parallel.js)
|
|
11
11
|
|
|
12
|
-
> **Other languages:** [Русский](./README.ru.md)
|
|
13
|
-
|
|
14
12
|
A library for parallel execution of JavaScript/TypeScript functions using Worker Threads in Node.js.
|
|
15
13
|
|
|
16
14
|
## Performance
|
|
@@ -30,9 +28,14 @@ Benchmarks on 4-core CPU:
|
|
|
30
28
|
- Simple API for parallel task execution
|
|
31
29
|
- Thread pool for efficient resource management
|
|
32
30
|
- Single thread support for one-off tasks
|
|
31
|
+
- Persistent threads for long-running background tasks
|
|
32
|
+
- Worker prewarming to reduce thread creation overhead
|
|
33
|
+
- Task TTL (timeout) support for better control
|
|
34
|
+
- Pool statistics and monitoring with `getStats()`
|
|
33
35
|
- Full TypeScript support
|
|
34
36
|
- Automatic recovery of crashed threads
|
|
35
37
|
- Array processing similar to `map()`, but parallel
|
|
38
|
+
- Automatic extraction and transfer of Transferable objects
|
|
36
39
|
|
|
37
40
|
## Installation
|
|
38
41
|
|
|
@@ -102,8 +105,8 @@ Use `Thread` for one-off operations:
|
|
|
102
105
|
```typescript
|
|
103
106
|
import { Thread } from 'stardust-parallel-js';
|
|
104
107
|
|
|
105
|
-
//
|
|
106
|
-
const thread =
|
|
108
|
+
// Execute function and wait for result
|
|
109
|
+
const thread = Thread.execute(
|
|
107
110
|
(text: string) => text.toUpperCase(),
|
|
108
111
|
['hello world']
|
|
109
112
|
);
|
|
@@ -112,8 +115,35 @@ const result = await thread.join();
|
|
|
112
115
|
console.log(result); // "HELLO WORLD"
|
|
113
116
|
|
|
114
117
|
// Arrow functions work!
|
|
115
|
-
const thread2 =
|
|
118
|
+
const thread2 = Thread.execute(x => x * 2, [21]);
|
|
116
119
|
console.log(await thread2.join()); // 42
|
|
120
|
+
|
|
121
|
+
// With TTL (timeout in milliseconds)
|
|
122
|
+
const thread3 = Thread.execute(
|
|
123
|
+
(n: number) => {
|
|
124
|
+
// Some heavy computation
|
|
125
|
+
return n * 2;
|
|
126
|
+
},
|
|
127
|
+
[42],
|
|
128
|
+
5000 // 5 seconds timeout
|
|
129
|
+
);
|
|
130
|
+
|
|
131
|
+
// Persistent thread for long-running tasks
|
|
132
|
+
const persistent = Thread.persistent(
|
|
133
|
+
() => {
|
|
134
|
+
setInterval(() => {
|
|
135
|
+
console.log('Running...');
|
|
136
|
+
}, 1000);
|
|
137
|
+
},
|
|
138
|
+
[]
|
|
139
|
+
);
|
|
140
|
+
|
|
141
|
+
persistent.onError((error) => {
|
|
142
|
+
console.error('Thread error:', error);
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
// Don't forget to terminate when done
|
|
146
|
+
persistent.terminate();
|
|
117
147
|
```
|
|
118
148
|
|
|
119
149
|
## Examples
|
|
@@ -167,6 +197,46 @@ const results = await pool.map([35, 36, 37, 38, 39, 40], n => {
|
|
|
167
197
|
await pool.terminate();
|
|
168
198
|
```
|
|
169
199
|
|
|
200
|
+
### Worker Prewarming for Better Performance
|
|
201
|
+
|
|
202
|
+
Prewarm workers to eliminate thread creation overhead for faster execution:
|
|
203
|
+
|
|
204
|
+
```typescript
|
|
205
|
+
import { Thread } from 'stardust-parallel-js';
|
|
206
|
+
import os from 'os';
|
|
207
|
+
|
|
208
|
+
// Prewarm workers at application startup
|
|
209
|
+
Thread.prewarm(os.cpus().length);
|
|
210
|
+
|
|
211
|
+
// Now all Thread.execute() calls will reuse prewarmed workers
|
|
212
|
+
// This is much faster than creating workers on-demand
|
|
213
|
+
const tasks = Array.from({ length: 100 }, (_, i) => i);
|
|
214
|
+
|
|
215
|
+
const results = await Promise.all(
|
|
216
|
+
tasks.map(async (n) => {
|
|
217
|
+
const thread = Thread.execute((x: number) => x * x, [n]);
|
|
218
|
+
return await thread.join();
|
|
219
|
+
})
|
|
220
|
+
);
|
|
221
|
+
|
|
222
|
+
console.log('All tasks completed:', results.length);
|
|
223
|
+
|
|
224
|
+
// Clean up when shutting down the application
|
|
225
|
+
Thread.clearPool();
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
**When to use prewarming:**
|
|
229
|
+
- Processing many small tasks with Thread.execute()
|
|
230
|
+
- Applications with predictable workloads
|
|
231
|
+
- Long-running services where startup time matters
|
|
232
|
+
- Reducing latency for first requests
|
|
233
|
+
|
|
234
|
+
**Comparison:**
|
|
235
|
+
```typescript
|
|
236
|
+
// Without prewarming: ~50ms per task (includes worker creation)
|
|
237
|
+
// With prewarming: ~5ms per task (workers already ready)
|
|
238
|
+
```
|
|
239
|
+
|
|
170
240
|
## Benchmarks
|
|
171
241
|
|
|
172
242
|
Run benchmarks:
|
|
@@ -181,29 +251,52 @@ npx tsx benchmarks/data-processing.ts
|
|
|
181
251
|
|
|
182
252
|
### ThreadPool
|
|
183
253
|
|
|
184
|
-
#### `constructor(size: number)`
|
|
254
|
+
#### `constructor(size: number, ttl?: number)`
|
|
185
255
|
Creates a thread pool of the specified size.
|
|
186
256
|
|
|
257
|
+
- `size` - Number of worker threads in the pool
|
|
258
|
+
- `ttl` - (optional) Default time to live in milliseconds for tasks
|
|
259
|
+
|
|
187
260
|
```typescript
|
|
261
|
+
// Without TTL
|
|
188
262
|
const pool = new ThreadPool(4);
|
|
263
|
+
|
|
264
|
+
// With default TTL of 10 seconds
|
|
265
|
+
const pool = new ThreadPool(4, 10000);
|
|
189
266
|
```
|
|
190
267
|
|
|
191
|
-
#### `execute<TArgs, TResult>(fn: (...args: TArgs) => TResult, args?: TArgs): Promise<TResult>`
|
|
268
|
+
#### `execute<TArgs, TResult>(fn: (...args: TArgs) => TResult, args?: TArgs, ttl?: number): Promise<TResult>`
|
|
192
269
|
Executes a function in an available thread from the pool.
|
|
193
270
|
|
|
271
|
+
- `ttl` - (optional) Time to live in milliseconds. Task will be rejected if it waits in queue longer than TTL.
|
|
272
|
+
|
|
194
273
|
```typescript
|
|
195
274
|
const result = await pool.execute((x: number) => x * x, [5]);
|
|
275
|
+
|
|
276
|
+
// With TTL - reject if task waits more than 3 seconds
|
|
277
|
+
const result = await pool.execute((x: number) => x * x, [5], 3000);
|
|
196
278
|
```
|
|
197
279
|
|
|
198
|
-
#### `map<T, R>(items: T[], fn: (item: T) => R): Promise<R[]>`
|
|
280
|
+
#### `map<T, R>(items: T[], fn: (item: T) => R, ttl?: number): Promise<R[]>`
|
|
199
281
|
Applies a function to each array element in parallel.
|
|
200
282
|
|
|
283
|
+
- `ttl` - (optional) Time to live in milliseconds for each task.
|
|
284
|
+
|
|
201
285
|
```typescript
|
|
202
|
-
//
|
|
286
|
+
// Without TTL
|
|
203
287
|
const results = await pool.map([1, 2, 3], n => n * 2);
|
|
204
288
|
|
|
205
|
-
//
|
|
206
|
-
const
|
|
289
|
+
// With TTL
|
|
290
|
+
const results = await pool.map([1, 2, 3], n => n * 2, 5000);
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
#### `getStats(): { totalWorkers: number; availableWorkers: number; busyWorkers: number; queuedTasks: number }`
|
|
294
|
+
Returns current pool statistics.
|
|
295
|
+
|
|
296
|
+
```typescript
|
|
297
|
+
const stats = pool.getStats();
|
|
298
|
+
console.log(`Busy workers: ${stats.busyWorkers}/${stats.totalWorkers}`);
|
|
299
|
+
console.log(`Queued tasks: ${stats.queuedTasks}`);
|
|
207
300
|
```
|
|
208
301
|
|
|
209
302
|
#### `terminate(): Promise<void>`
|
|
@@ -215,20 +308,84 @@ await pool.terminate();
|
|
|
215
308
|
|
|
216
309
|
### Thread
|
|
217
310
|
|
|
218
|
-
#### `
|
|
219
|
-
Creates a new thread to execute a function.
|
|
311
|
+
#### `Thread.execute<T, TArgs>(fn: (...args: TArgs) => T, args?: TArgs, ttl?: number): ExecutableThread<T, TArgs>`
|
|
312
|
+
Creates a new thread to execute a function once.
|
|
313
|
+
|
|
314
|
+
- `ttl` - (optional) Time to live in milliseconds. Thread will be terminated if execution takes longer.
|
|
315
|
+
|
|
316
|
+
```typescript
|
|
317
|
+
const thread = Thread.execute((x: number) => x * x, [5]);
|
|
318
|
+
const result = await thread.join();
|
|
319
|
+
|
|
320
|
+
// With TTL
|
|
321
|
+
const thread = Thread.execute(
|
|
322
|
+
(x: number) => x * x,
|
|
323
|
+
[5],
|
|
324
|
+
5000 // 5 seconds timeout
|
|
325
|
+
);
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
#### `Thread.persistent<T, TArgs>(fn: (...args: TArgs) => T, args?: TArgs): PersistentThread<T, TArgs>`
|
|
329
|
+
Creates a persistent thread for long-running tasks.
|
|
330
|
+
|
|
331
|
+
```typescript
|
|
332
|
+
const persistent = Thread.persistent(() => {
|
|
333
|
+
setInterval(() => {
|
|
334
|
+
console.log('Background task');
|
|
335
|
+
}, 1000);
|
|
336
|
+
}, []);
|
|
337
|
+
|
|
338
|
+
persistent.onError((error) => {
|
|
339
|
+
console.error('Thread error:', error);
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
persistent.terminate(); // Don't forget to clean up
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
#### `Thread.prewarm(count?: number): void`
|
|
346
|
+
Prewarms a pool of workers to reduce thread creation overhead.
|
|
220
347
|
|
|
221
348
|
```typescript
|
|
222
|
-
|
|
349
|
+
// Prewarm 4 workers (default)
|
|
350
|
+
Thread.prewarm();
|
|
351
|
+
|
|
352
|
+
// Prewarm specific number of workers
|
|
353
|
+
Thread.prewarm(8);
|
|
354
|
+
|
|
355
|
+
// Now Thread.execute() will reuse prewarmed workers
|
|
356
|
+
const thread = Thread.execute((x: number) => x * 2, [21]);
|
|
223
357
|
```
|
|
224
358
|
|
|
225
|
-
#### `
|
|
226
|
-
|
|
359
|
+
#### `Thread.clearPool(): void`
|
|
360
|
+
Clears the prewarmed worker pool and terminates all workers.
|
|
361
|
+
|
|
362
|
+
```typescript
|
|
363
|
+
Thread.clearPool();
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
#### `ExecutableThread.join(): Promise<T>`
|
|
367
|
+
Waits for execution to complete and returns the result. Automatically terminates or returns thread to pool.
|
|
227
368
|
|
|
228
369
|
```typescript
|
|
229
370
|
const result = await thread.join();
|
|
230
371
|
```
|
|
231
372
|
|
|
373
|
+
#### `PersistentThread.onError(callback: (error: Error) => void): this`
|
|
374
|
+
Registers an error handler for persistent threads.
|
|
375
|
+
|
|
376
|
+
```typescript
|
|
377
|
+
persistent.onError((error) => {
|
|
378
|
+
console.error('Error in persistent thread:', error);
|
|
379
|
+
});
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
#### `PersistentThread.terminate(): void`
|
|
383
|
+
Terminates a persistent thread.
|
|
384
|
+
|
|
385
|
+
```typescript
|
|
386
|
+
persistent.terminate();
|
|
387
|
+
```
|
|
388
|
+
|
|
232
389
|
## Important Notes
|
|
233
390
|
|
|
234
391
|
- Functions execute in an isolated context (separate Worker Thread)
|
|
@@ -280,9 +437,12 @@ const pool = new ThreadPool(os.cpus().length * 2);
|
|
|
280
437
|
## Roadmap
|
|
281
438
|
|
|
282
439
|
- [x] Support for transferable objects for large data
|
|
440
|
+
- [x] Task TTL (time to live) support
|
|
441
|
+
- [x] Persistent threads for long-running tasks
|
|
442
|
+
- [x] Worker prewarming for reduced overhead
|
|
443
|
+
- [x] Pool statistics and monitoring
|
|
283
444
|
- [ ] Automatic selection of optimal pool size
|
|
284
445
|
- [ ] Task prioritization
|
|
285
|
-
- [ ] Monitoring and statistics
|
|
286
446
|
- [ ] Support for async functions in threads
|
|
287
447
|
|
|
288
448
|
## Feedback
|
|
@@ -297,10 +457,4 @@ Found a bug or have an idea? [Create an issue](https://github.com/b1411/parallel
|
|
|
297
457
|
|
|
298
458
|
MIT © [b1411](https://github.com/b1411)
|
|
299
459
|
|
|
300
|
-
---
|
|
301
|
-
|
|
302
|
-
<p align="center">
|
|
303
|
-
Made with ❤️ for the Node.js community
|
|
304
|
-
</p>
|
|
305
|
-
|
|
306
460
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseThread.d.ts","sourceRoot":"","sources":["../../../src/primitives/Thread/BaseThread.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"BaseThread.d.ts","sourceRoot":"","sources":["../../../src/primitives/Thread/BaseThread.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAElD,8BAAsB,UAAU;IAC5B,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC;IACzB,SAAS,CAAC,UAAU,UAAS;;IAU7B,OAAO,CAAC,MAAM,CAAC,UAAU,CAAgB;IACzC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAS;IAE/B,MAAM,CAAC,OAAO,CAAC,KAAK,SAA6B;IAQjD,MAAM,CAAC,SAAS;IAQhB,SAAS,CAAC,YAAY;IAStB,SAAS;CAMZ"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { createWorker } from "../../utils/workerFactory.js";
|
|
2
|
+
import { availableParallelism } from "node:os";
|
|
2
3
|
export class BaseThread {
|
|
3
4
|
worker;
|
|
4
5
|
terminated = false;
|
|
@@ -7,15 +8,15 @@ export class BaseThread {
|
|
|
7
8
|
this.worker = BaseThread.workerPool.pop();
|
|
8
9
|
}
|
|
9
10
|
else {
|
|
10
|
-
this.worker = createWorker()
|
|
11
|
+
this.worker = createWorker();
|
|
11
12
|
}
|
|
12
13
|
}
|
|
13
14
|
static workerPool = [];
|
|
14
15
|
static usePool = false;
|
|
15
|
-
static prewarm(count =
|
|
16
|
+
static prewarm(count = availableParallelism() - 1) {
|
|
16
17
|
this.usePool = true;
|
|
17
18
|
for (let i = 0; i < count; i++) {
|
|
18
|
-
const worker = createWorker()
|
|
19
|
+
const worker = createWorker();
|
|
19
20
|
this.workerPool.push(worker);
|
|
20
21
|
}
|
|
21
22
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseThread.js","sourceRoot":"","sources":["../../../src/primitives/Thread/BaseThread.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"BaseThread.js","sourceRoot":"","sources":["../../../src/primitives/Thread/BaseThread.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAG/C,MAAM,OAAgB,UAAU;IAClB,MAAM,CAAS;IACf,UAAU,GAAG,KAAK,CAAC;IAE7B;QACI,IAAI,UAAU,CAAC,OAAO,IAAI,UAAU,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACzD,IAAI,CAAC,MAAM,GAAG,UAAU,CAAC,UAAU,CAAC,GAAG,EAAY,CAAC;QACxD,CAAC;aAAM,CAAC;YACJ,IAAI,CAAC,MAAM,GAAG,YAAY,EAAE,CAAC;QACjC,CAAC;IACL,CAAC;IAEO,MAAM,CAAC,UAAU,GAAa,EAAE,CAAC;IACjC,MAAM,CAAC,OAAO,GAAG,KAAK,CAAC;IAE/B,MAAM,CAAC,OAAO,CAAC,KAAK,GAAG,oBAAoB,EAAE,GAAG,CAAC;QAC7C,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;YAC7B,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;YAC9B,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACjC,CAAC;IACL,CAAC;IAED,MAAM,CAAC,SAAS;QACZ,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACnC,MAAM,CAAC,SAAS,EAAE,CAAC;QACvB,CAAC;QACD,IAAI,CAAC,UAAU,GAAG,EAAE,CAAC;QACrB,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;IACzB,CAAC;IAES,YAAY;QAClB,IAAI,CAAC,IAAI,CAAC,UAAU,IAAI,UAAU,CAAC,OAAO,EAAE,CAAC;YACzC,UAAU,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACxC,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QAC3B,CAAC;aAAM,CAAC;YACJ,IAAI,CAAC,SAAS,EAAE,CAAC;QACrB,CAAC;IACL,CAAC;IAED,SAAS;QACL,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;YACnB,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;YACxB,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QAC3B,CAAC;IACL,CAAC"}
|
|
@@ -17,9 +17,9 @@ export class ThreadPool {
|
|
|
17
17
|
initWorkers() {
|
|
18
18
|
for (let i = 0; i < this.size; i++) {
|
|
19
19
|
const worker = createWorker();
|
|
20
|
-
this.setupWorkerHandlers(worker
|
|
21
|
-
this.workers.push(worker
|
|
22
|
-
this.availableWorkers.push(worker
|
|
20
|
+
this.setupWorkerHandlers(worker);
|
|
21
|
+
this.workers.push(worker);
|
|
22
|
+
this.availableWorkers.push(worker);
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
25
|
setupWorkerHandlers(worker) {
|
|
@@ -65,9 +65,9 @@ export class ThreadPool {
|
|
|
65
65
|
this.availableWorkers = this.availableWorkers.filter(worker => worker !== crashedWorker);
|
|
66
66
|
crashedWorker.terminate();
|
|
67
67
|
const newWorker = createWorker();
|
|
68
|
-
this.setupWorkerHandlers(newWorker
|
|
69
|
-
this.workers.push(newWorker
|
|
70
|
-
this.availableWorkers.push(newWorker
|
|
68
|
+
this.setupWorkerHandlers(newWorker);
|
|
69
|
+
this.workers.push(newWorker);
|
|
70
|
+
this.availableWorkers.push(newWorker);
|
|
71
71
|
this.processQueue();
|
|
72
72
|
}
|
|
73
73
|
processQueue() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ThreadPool.js","sourceRoot":"","sources":["../../src/primitives/ThreadPool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAqB,MAAM,qBAAqB,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAClD,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AAYvE,MAAM,OAAO,UAAU;IAOC;IANZ,OAAO,GAAa,EAAE,CAAC;IACvB,gBAAgB,GAAa,EAAE,CAAC;IAChC,SAAS,GAAG,IAAI,KAAK,EAAiB,CAAC;IACvC,WAAW,GAAG,IAAI,GAAG,EAAyB,CAAC;IAC/C,UAAU,CAAqB;IAEvC,YAAoB,IAAY,EAAE,GAAY;QAA1B,SAAI,GAAJ,IAAI,CAAQ;QAC5B,IAAI,CAAC,UAAU,GAAG,GAAG,CAAC;QACtB,IAAI,CAAC,WAAW,EAAE,CAAC;IACvB,CAAC;IAEO,WAAW;QACf,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC;YACjC,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;YAC9B,IAAI,CAAC,mBAAmB,CAAC,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"ThreadPool.js","sourceRoot":"","sources":["../../src/primitives/ThreadPool.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
import { Worker
|
|
2
|
-
export declare function createWorker():
|
|
3
|
-
worker: Worker;
|
|
4
|
-
run<R, TArgs extends unknown[] = unknown[]>(fn: (...args: TArgs) => R, args?: TArgs, transferables?: Transferable[]): void;
|
|
5
|
-
};
|
|
1
|
+
import { Worker } from "node:worker_threads";
|
|
2
|
+
export declare function createWorker(): Worker;
|
|
6
3
|
//# sourceMappingURL=workerFactory.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workerFactory.d.ts","sourceRoot":"","sources":["../../src/utils/workerFactory.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"workerFactory.d.ts","sourceRoot":"","sources":["../../src/utils/workerFactory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AA4C7C,wBAAgB,YAAY,WAE3B"}
|
|
@@ -4,38 +4,7 @@ const workerCode = `
|
|
|
4
4
|
|
|
5
5
|
parentPort.on('message', async ({ type, fn, args }) => {
|
|
6
6
|
try {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
// Detect async keyword
|
|
10
|
-
const isAsync = /^async\\s+/.test(cleanFn);
|
|
11
|
-
cleanFn = cleanFn.replace(/^async\\s+/, '');
|
|
12
|
-
|
|
13
|
-
// Arrow function conversion
|
|
14
|
-
const arrowMatch = cleanFn.match(/^\\(([^)]*)\\)\\s*=>\\s*(.+)$/s);
|
|
15
|
-
if (arrowMatch) {
|
|
16
|
-
const params = arrowMatch[1];
|
|
17
|
-
const body = arrowMatch[2].trim();
|
|
18
|
-
|
|
19
|
-
if (body.startsWith('{') && body.endsWith('}')) {
|
|
20
|
-
cleanFn = \`\${isAsync ? 'async ' : ''}function(\${params}) \${body}\`;
|
|
21
|
-
} else {
|
|
22
|
-
cleanFn = \`\${isAsync ? 'async ' : ''}function(\${params}) { return \${body} }\`;
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
const singleArrowMatch = cleanFn.match(/^([a-zA-Z_$][a-zA-Z0-9_$]*)\\s*=>\\s*(.+)$/s);
|
|
27
|
-
if (singleArrowMatch) {
|
|
28
|
-
const param = singleArrowMatch[1];
|
|
29
|
-
const body = singleArrowMatch[2].trim();
|
|
30
|
-
|
|
31
|
-
if (body.startsWith('{') && body.endsWith('}')) {
|
|
32
|
-
cleanFn = \`\${isAsync ? 'async ' : ''}function(\${param}) \${body}\`;
|
|
33
|
-
} else {
|
|
34
|
-
cleanFn = \`\${isAsync ? 'async ' : ''}function(\${param}) { return \${body} }\`;
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const func = eval('(' + cleanFn + ')');
|
|
7
|
+
const func = eval('(' + fn + ')');
|
|
39
8
|
|
|
40
9
|
// Execute или Persistent режим
|
|
41
10
|
if (type === 'persistent') {
|
|
@@ -72,18 +41,6 @@ const workerCode = `
|
|
|
72
41
|
});
|
|
73
42
|
`;
|
|
74
43
|
export function createWorker() {
|
|
75
|
-
|
|
76
|
-
return {
|
|
77
|
-
worker,
|
|
78
|
-
run(fn, args = [], transferables) {
|
|
79
|
-
const message = {
|
|
80
|
-
type: 'execute',
|
|
81
|
-
fn: fn.toString(),
|
|
82
|
-
args
|
|
83
|
-
};
|
|
84
|
-
// Поддержка старого API без type (для обратной совместимости)
|
|
85
|
-
worker.postMessage(message, transferables || []);
|
|
86
|
-
}
|
|
87
|
-
};
|
|
44
|
+
return new Worker(workerCode, { eval: true });
|
|
88
45
|
}
|
|
89
46
|
//# sourceMappingURL=workerFactory.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workerFactory.js","sourceRoot":"","sources":["../../src/utils/workerFactory.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"workerFactory.js","sourceRoot":"","sources":["../../src/utils/workerFactory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAE7C,MAAM,UAAU,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwClB,CAAC;AAEF,MAAM,UAAU,YAAY;IACxB,OAAO,IAAI,MAAM,CAAC,UAAU,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;AAClD,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "stardust-parallel-js",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.1.0",
|
|
4
4
|
"description": "Simple parallel execution library for Node.js using Worker Threads. Execute CPU-intensive tasks with thread pools and isolated workers. Supports both regular and arrow functions.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
package/README.ru.md
DELETED
|
@@ -1,309 +0,0 @@
|
|
|
1
|
-
# ⚡ stardust-parallel-js
|
|
2
|
-
|
|
3
|
-
[](https://www.npmjs.com/package/stardust-parallel-js)
|
|
4
|
-
[](https://www.npmjs.com/package/stardust-parallel-js)
|
|
5
|
-
[](https://opensource.org/licenses/MIT)
|
|
6
|
-
[](https://github.com/b1411/parallel.js)
|
|
7
|
-
[](https://nodejs.org)
|
|
8
|
-
[](https://www.typescriptlang.org/)
|
|
9
|
-
[](https://bundlephobia.com/package/stardust-parallel-js)
|
|
10
|
-
[](https://github.com/b1411/parallel.js)
|
|
11
|
-
|
|
12
|
-
> **Другие языки:** [English](./README.md)
|
|
13
|
-
|
|
14
|
-
Библиотека для параллельного выполнения JavaScript/TypeScript функций с использованием Worker Threads в Node.js.
|
|
15
|
-
|
|
16
|
-
## Производительность
|
|
17
|
-
|
|
18
|
-
Бенчмарки на 4-ядерном CPU:
|
|
19
|
-
|
|
20
|
-
| Задача | Последовательно | Параллельно (4 потока) | Ускорение |
|
|
21
|
-
|--------|----------------|------------------------|-----------|
|
|
22
|
-
| **Вычисление Fibonacci(35-42)** | 5113 мс | 2606 мс | **1.96x** |
|
|
23
|
-
| **Обработка 50 элементов** | 936 мс | 344 мс | **2.72x** |
|
|
24
|
-
|
|
25
|
-
> Улучшение производительности: до 63% на CPU-интенсивных задачах.
|
|
26
|
-
|
|
27
|
-
## Возможности
|
|
28
|
-
|
|
29
|
-
- Реальное ускорение на многоядерных процессорах
|
|
30
|
-
- Простой API для параллельного выполнения задач
|
|
31
|
-
- Пул потоков для эффективного управления ресурсами
|
|
32
|
-
- Поддержка отдельных потоков для разовых задач
|
|
33
|
-
- Полная поддержка TypeScript
|
|
34
|
-
- Автоматическое восстановление упавших потоков
|
|
35
|
-
- Обработка массивов аналогично `map()`, но параллельно
|
|
36
|
-
|
|
37
|
-
## Установка
|
|
38
|
-
|
|
39
|
-
```bash
|
|
40
|
-
npm install stardust-parallel-js
|
|
41
|
-
# или
|
|
42
|
-
pnpm install stardust-parallel-js
|
|
43
|
-
# или
|
|
44
|
-
yarn add stardust-parallel-js
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
## Быстрый старт
|
|
48
|
-
|
|
49
|
-
Пример базового использования:
|
|
50
|
-
|
|
51
|
-
```typescript
|
|
52
|
-
import { ThreadPool } from 'stardust-parallel-js';
|
|
53
|
-
|
|
54
|
-
const pool = new ThreadPool(4);
|
|
55
|
-
|
|
56
|
-
// Последовательное выполнение
|
|
57
|
-
const results = data.map(item => heavyComputation(item));
|
|
58
|
-
|
|
59
|
-
// Параллельное выполнение
|
|
60
|
-
const results = await pool.map(data, item => heavyComputation(item));
|
|
61
|
-
|
|
62
|
-
await pool.terminate();
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
## Использование
|
|
66
|
-
|
|
67
|
-
### ThreadPool - Пул потоков (рекомендуется)
|
|
68
|
-
|
|
69
|
-
Используйте `ThreadPool` для обработки множества задач с максимальной эффективностью:
|
|
70
|
-
|
|
71
|
-
```typescript
|
|
72
|
-
import { ThreadPool } from 'stardust-parallel-js';
|
|
73
|
-
|
|
74
|
-
// Создаем пул из 4 потоков (по числу ядер CPU)
|
|
75
|
-
const pool = new ThreadPool(4);
|
|
76
|
-
|
|
77
|
-
// Обработка массива параллельно
|
|
78
|
-
const numbers = [1, 2, 3, 4, 5, 6, 7, 8];
|
|
79
|
-
const squares = await pool.map(numbers, (n: number) => n * n);
|
|
80
|
-
console.log(squares); // [1, 4, 9, 16, 25, 36, 49, 64]
|
|
81
|
-
|
|
82
|
-
// CPU-интенсивные вычисления
|
|
83
|
-
const result = await pool.execute(
|
|
84
|
-
(n: number) => {
|
|
85
|
-
let sum = 0;
|
|
86
|
-
for (let i = 0; i < n; i++) {
|
|
87
|
-
sum += Math.sqrt(i);
|
|
88
|
-
}
|
|
89
|
-
return sum;
|
|
90
|
-
},
|
|
91
|
-
[1000000]
|
|
92
|
-
);
|
|
93
|
-
|
|
94
|
-
// Освобождаем ресурсы
|
|
95
|
-
await pool.terminate();
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
### Thread - Отдельный поток (для простых задач)
|
|
99
|
-
|
|
100
|
-
Используйте `Thread` для разовых операций:
|
|
101
|
-
|
|
102
|
-
```typescript
|
|
103
|
-
import { Thread } from 'stardust-parallel-js';
|
|
104
|
-
|
|
105
|
-
// Запустить и дождаться результата
|
|
106
|
-
const thread = new Thread(
|
|
107
|
-
(text: string) => text.toUpperCase(),
|
|
108
|
-
['hello world']
|
|
109
|
-
);
|
|
110
|
-
|
|
111
|
-
const result = await thread.join();
|
|
112
|
-
console.log(result); // "HELLO WORLD"
|
|
113
|
-
|
|
114
|
-
// Стрелочные функции работают!
|
|
115
|
-
const thread2 = new Thread(x => x * 2, [21]);
|
|
116
|
-
console.log(await thread2.join()); // 42
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
## Примеры
|
|
120
|
-
|
|
121
|
-
### Обработка изображений
|
|
122
|
-
|
|
123
|
-
```typescript
|
|
124
|
-
import { ThreadPool } from 'stardust-parallel-js';
|
|
125
|
-
|
|
126
|
-
const pool = new ThreadPool(8);
|
|
127
|
-
const images = ['img1.jpg', 'img2.jpg', /* ... */ 'img100.jpg'];
|
|
128
|
-
|
|
129
|
-
// Обрабатываем 100 изображений параллельно
|
|
130
|
-
const processed = await pool.map(images, (path: string) => {
|
|
131
|
-
const fs = require('fs');
|
|
132
|
-
const sharp = require('sharp');
|
|
133
|
-
// Сложная обработка изображения
|
|
134
|
-
return processImage(path);
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
await pool.terminate();
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
### Парсинг больших данных
|
|
141
|
-
|
|
142
|
-
```typescript
|
|
143
|
-
const pool = new ThreadPool(4);
|
|
144
|
-
const chunks = splitDataIntoChunks(bigData, 1000);
|
|
145
|
-
|
|
146
|
-
// Парсим каждый чунк параллельно
|
|
147
|
-
const parsed = await pool.map(chunks, (chunk: any[]) => {
|
|
148
|
-
return chunk.map(item => parseComplexData(item));
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
await pool.terminate();
|
|
152
|
-
```
|
|
153
|
-
|
|
154
|
-
### Вычисления и аналитика
|
|
155
|
-
|
|
156
|
-
```typescript
|
|
157
|
-
const pool = new ThreadPool(4);
|
|
158
|
-
|
|
159
|
-
const results = await pool.map([35, 36, 37, 38, 39, 40], n => {
|
|
160
|
-
function fibonacci(num: number): number {
|
|
161
|
-
if (num <= 1) return num;
|
|
162
|
-
return fibonacci(num - 1) + fibonacci(num - 2);
|
|
163
|
-
}
|
|
164
|
-
return fibonacci(n);
|
|
165
|
-
});
|
|
166
|
-
|
|
167
|
-
await pool.terminate();
|
|
168
|
-
```
|
|
169
|
-
|
|
170
|
-
## Бенчмарки
|
|
171
|
-
|
|
172
|
-
Запуск бенчмарков:
|
|
173
|
-
|
|
174
|
-
```bash
|
|
175
|
-
npm run build
|
|
176
|
-
npx tsx benchmarks/cpu-intensive.ts
|
|
177
|
-
npx tsx benchmarks/data-processing.ts
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
## API Reference
|
|
181
|
-
|
|
182
|
-
### ThreadPool
|
|
183
|
-
|
|
184
|
-
#### `constructor(size: number)`
|
|
185
|
-
Создает пул потоков заданного размера.
|
|
186
|
-
|
|
187
|
-
```typescript
|
|
188
|
-
const pool = new ThreadPool(4);
|
|
189
|
-
```
|
|
190
|
-
|
|
191
|
-
#### `execute<TArgs, TResult>(fn: (...args: TArgs) => TResult, args?: TArgs): Promise<TResult>`
|
|
192
|
-
Выполняет функцию в доступном потоке из пула.
|
|
193
|
-
|
|
194
|
-
```typescript
|
|
195
|
-
const result = await pool.execute(
|
|
196
|
-
#### `map<T, R>(items: T[], fn: (item: T) => R): Promise<R[]>`
|
|
197
|
-
Применяет функцию к каждому элементу массива параллельно.
|
|
198
|
-
|
|
199
|
-
```typescript
|
|
200
|
-
// Стрелочная функция
|
|
201
|
-
const results = await pool.map([1, 2, 3], n => n * 2);
|
|
202
|
-
|
|
203
|
-
// Обычная функция
|
|
204
|
-
const results2 = await pool.map([1, 2, 3], function(n) { return n * 2; });
|
|
205
|
-
```# `map<T, R>(items: T[], fn: (item: T) => R): Promise<R[]>`
|
|
206
|
-
Применяет функцию к каждому элементу массива параллельно.
|
|
207
|
-
|
|
208
|
-
```typescript
|
|
209
|
-
const results = await pool.map([1, 2, 3], (n) => n * 2);
|
|
210
|
-
```
|
|
211
|
-
|
|
212
|
-
#### `terminate(): Promise<void>`
|
|
213
|
-
Останавливает все потоки и освобождает ресурсы.
|
|
214
|
-
|
|
215
|
-
```typescript
|
|
216
|
-
await pool.terminate();
|
|
217
|
-
```
|
|
218
|
-
|
|
219
|
-
### Thread
|
|
220
|
-
|
|
221
|
-
#### `constructor<T, TArgs>(fn: (...args: TArgs) => T, args?: TArgs)`
|
|
222
|
-
Создает новый поток для выполнения функции.
|
|
223
|
-
|
|
224
|
-
```typescript
|
|
225
|
-
const thread = new Thread((x: number) => x * x, [5]);
|
|
226
|
-
```
|
|
227
|
-
|
|
228
|
-
#### `join(): Promise<T>`
|
|
229
|
-
Ожидает завершения выполнения и возвращает результат. Автоматически завершает поток.
|
|
230
|
-
|
|
231
|
-
```typescript
|
|
232
|
-
const result = await thread.join();
|
|
233
|
-
```
|
|
234
|
-
|
|
235
|
-
## Важные замечания
|
|
236
|
-
|
|
237
|
-
- Функции выполняются в изолированном контексте (отдельный Worker Thread)
|
|
238
|
-
- Аргументы и результаты должны быть сериализуемыми
|
|
239
|
-
- Замыкания не работают - функции не имеют доступа к внешним переменным
|
|
240
|
-
- Поддерживаются обычные и стрелочные функции
|
|
241
|
-
- `require()` доступен внутри функций для использования Node.js модулей
|
|
242
|
-
- Лучше всего подходит для CPU-интенсивных задач (вычисления, обработка данных)
|
|
243
|
-
- Для I/O операций (чтение файлов, сеть) используйте async/await вместо потоков
|
|
244
|
-
|
|
245
|
-
## Когда использовать
|
|
246
|
-
|
|
247
|
-
**Используйте stardust-parallel-js когда:**
|
|
248
|
-
- Обрабатываете большие массивы данных
|
|
249
|
-
- Выполняете сложные вычисления
|
|
250
|
-
- Парсите или трансформируете данные
|
|
251
|
-
- Обрабатываете изображения/видео
|
|
252
|
-
- Нужно использовать все ядра CPU
|
|
253
|
-
|
|
254
|
-
**Не используйте когда:**
|
|
255
|
-
- Простые операции (быстрее выполнить последовательно)
|
|
256
|
-
- I/O операции (файлы, сеть, БД) - они уже асинхронные
|
|
257
|
-
- Работаете с DOM (только в Node.js)
|
|
258
|
-
|
|
259
|
-
## Выбор размера пула
|
|
260
|
-
|
|
261
|
-
```typescript
|
|
262
|
-
import os from 'os';
|
|
263
|
-
|
|
264
|
-
// Оптимально: количество CPU ядер
|
|
265
|
-
const pool = new ThreadPool(os.cpus().length);
|
|
266
|
-
|
|
267
|
-
// Для CPU-интенсивных задач
|
|
268
|
-
const pool = new ThreadPool(os.cpus().length - 1); // оставить 1 ядро для системы
|
|
269
|
-
|
|
270
|
-
// Для смешанной нагрузки
|
|
271
|
-
const pool = new ThreadPool(os.cpus().length * 2);
|
|
272
|
-
```
|
|
273
|
-
|
|
274
|
-
## Сравнение с альтернативами
|
|
275
|
-
|
|
276
|
-
| Решение | Простота | Производительность | TypeScript | Размер |
|
|
277
|
-
|---------|----------|-------------------|------------|--------|
|
|
278
|
-
| **stardust-parallel-js** | Высокая | Высокая | Полная | 9.3kB |
|
|
279
|
-
| worker_threads | Средняя | Высокая | Частичная | Встроено |
|
|
280
|
-
| cluster | Средняя | Средняя | Частичная | Встроено |
|
|
281
|
-
| child_process | Низкая | Низкая | Нет | Встроено |
|
|
282
|
-
|
|
283
|
-
## Roadmap
|
|
284
|
-
|
|
285
|
-
- [x] Поддержка transferable objects для больших данных
|
|
286
|
-
- [ ] Автоматический выбор оптимального размера пула
|
|
287
|
-
- [ ] Приоритизация задач
|
|
288
|
-
- [ ] Мониторинг и статистика
|
|
289
|
-
- [ ] Поддержка async функций в потоках
|
|
290
|
-
|
|
291
|
-
## Обратная связь
|
|
292
|
-
|
|
293
|
-
Нашли баг или есть идея? [Создайте issue](https://github.com/b1411/parallel.js).
|
|
294
|
-
|
|
295
|
-
## Требования
|
|
296
|
-
|
|
297
|
-
- Node.js >= 14.0.0 (с поддержкой Worker Threads)
|
|
298
|
-
|
|
299
|
-
## Лицензия
|
|
300
|
-
|
|
301
|
-
MIT © [b1411](https://github.com/b1411)
|
|
302
|
-
|
|
303
|
-
---
|
|
304
|
-
|
|
305
|
-
<p align="center">
|
|
306
|
-
Сделано с ❤️ для Node.js сообщества
|
|
307
|
-
</p>
|
|
308
|
-
|
|
309
|
-
|