@@ -9,7 +9,7 @@ Concurrent.js is a library that enables non-blocking computation on JavaScript R
9
9
- [x] Sharing workers
10
10
- [x] Parallel execution
11
11
- [x] Reactive concurrency
12
- - [ ] Sandboxing
12
+ - [ ] Isolation
13
13
14
14
## Technical Facts
15
15
@@ -38,12 +38,22 @@ npm i @bitair/concurrent.js
38
38
39
39
## Usage
40
40
41
+ At its highest level of design, Concurrent.js is a dynamic module importer that loads a module into a web worker:
42
+
41
43
``` js
42
44
import { concurrent } from ' @bitair/concurrent.js'
45
+ // In Deno
46
+ // import { concurrent } from 'https://deno.land/x/[email protected] /mod.ts'
47
+
48
+ // Import a module
49
+ const MyModule = concurrent .import (new URL (' ./sample_module.js' , import .meta.url))
50
+ // In a CommonJS module
51
+ // const MyModule = concurrent.import(path.join(__dirname, 'sample_module.js'))
43
52
44
- // Import and load a JS module into a worker
45
- const { SampleObject , sampleFunction } =
46
- await concurrent .import (new URL (' ./sample_module.js' , import .meta.url)).load()
53
+ // Load it into a web worker
54
+ const { SampleObject , sampleFunction } = await MyModule .load ()
55
+ // Load it into another web worker
56
+ // const { SampleObject: SampleObject2, sampleFunction: sampleFunction2 } = await MyModule.load()
47
57
48
58
// Run a function
49
59
const result = await sampleFunction (/* ...args*/ )
@@ -66,17 +76,59 @@ await concurrent.terminate()
66
76
## Samples
67
77
68
78
- Browser
79
+
69
80
- [Basic usage](./apps/sample/browser/)
70
- - [Tensorflow.js](./apps/sample/browser-tensorflow/)
81
+ - [Tensorflow.js usage](./apps/sample/browser-tensorflow/)
82
+
83
+ - Node & Bun
71
84
72
- - Node
73
85
- [Basic usage](./apps/sample/node/)
74
86
75
87
- Deno
76
88
- [Basic usage](./apps/sample/deno/)
77
89
90
+ ## Benchmark
91
+
92
+ The following results demonstrate the average execution time and CPU usage of running 10 concurrent calculations (10 iterations) of the factorial of 50,000 on various JavaScript runtime environments (RTEs). These calculations were performed on a Quad-core AMD APU with a base clock rate of 2.2GHz within a freshly installed isolated Ubuntu VM.
93
+
94
+
95
+ (There are 213,237 digits in the factorial of 50,000)
96
+
97
+ | | RTE | JS Engine | Execution Time | CPU Usage |
98
+ |---|---------------------|----------------------|------------------------|-----------|
99
+ | 1 | **Deno** (v1.40) | V8 | 7.9168s | 100% |
100
+ | 2 | **Chrome*** (v121.0) | V8 | 7.919s | 100% |
101
+ | 3 | **Node** (v20.11) | V8 | 8.117s | 100% |
102
+ | 4 | **Servo** (v0.0.1-c94d584) | SpiderMonkey | 31.267s | 99% |
103
+ | 5 | **LibreWolf** (122.0) | SpiderMonkey | 35.417s | 92% |
104
+ | 6 | **Firefox*** (v125.0) | SpiderMonkey | 49.061s | 95% |
105
+ | 7 | **Bun** (v1.0.26) | JavaScriptCore | 51.502s | 99% |
106
+ | 8 | **GNOME Web** (v45.2) | JavaScriptCore | 59.058s | 75% |
107
+
108
+ * A headless environment was used for benchmarking.
109
+
110
+ To benchmark Node, Deno, Bun RTEs as well as Chrome and Firefox browsers use the [benchmarking app](./apps/benchmark/):
111
+ ` ` ` bash
112
+ git clone https: // github.com/bitair-org/concurrent.js.git
113
+ cd concurrent .js / apps/ benchmark
114
+ npm i
115
+ npm start # This command starts a web server required by the headless browsers . Do not open the http: // 127.0.0.1:8080 address
116
+ npm run benchmark
117
+ ` ` `
118
+
119
+ For benchmarking other browsers, use the [browser basic usage sample](./apps/sample/browser)
120
+ ` ` ` bash
121
+ git clone https: // github.com/bitair-org/concurrent.js.git
122
+ cd concurrent .js / apps/ sample/ browser
123
+ npm i
124
+ npm start # Open the http: // 127.0.0.1:8080 address in the target browser
125
+ ` ` `
126
+
127
+
78
128
## Parallelism
79
129
130
+ To run each function call or object instance on a separate CPU core, the ` load` method of the imported module must be called for each function call or object instance individually:
131
+
80
132
` ` ` js
81
133
import { concurrent } from ' @bitair/concurrent.js'
82
134
@@ -97,6 +149,7 @@ await concurrent.terminate()
97
149
` ` `
98
150
99
151
## Reactive Concurrency
152
+ The reactive concurrency feature provides a bidirectional channel for messaging. A message can be replied to by returning a value:
100
153
101
154
` services/ index .mjs `
102
155
@@ -125,8 +178,7 @@ export async function reactiveAdd(channel /*: IChannel */) {
125
178
` ` ` js
126
179
import { concurrent , Channel } from ' @bitair/concurrent.js'
127
180
128
- const { reactiveAdd } =
129
- await concurrent .import (new URL (' ./services/index.mjs' , import .meta.url)).load()
181
+ const { reactiveAdd } = await concurrent .import (new URL (' ./services/index.mjs' , import .meta.url)).load()
130
182
131
183
const channel = new Channel ((onmessage , postMessage ) => {
132
184
const arr = [1 , 2 , 3 , 4 ]
@@ -171,14 +223,17 @@ concurrent.config(settings: ConcurrencySettings): void
171
223
Configures the global settings of Concurrent.js.
172
224
173
225
- ` settings: ConcurrencySettings`
226
+
174
227
- ` settings .maxThreads : number [default= 1 ]`
175
-
228
+
176
229
The maximum number of available threads to be spawned.
230
+
177
231
- ` settings .threadIdleTimeout : number | typeof Infinity [default= Infinity ]`
178
-
232
+
179
233
Number of minutes before Concurrent.js terminates an idle thread.
234
+
180
235
- ` settings .minThreads : number [default= 0 ]`
181
-
236
+
182
237
The number of threads created when Concurrent.js starts and kept alive to avoid thread recreation overhead.
183
238
184
239
` ` ` ts
@@ -190,7 +245,6 @@ Terminates Concurrent.js.
190
245
- ` force?: boolean [Not implemented]`
191
246
Forces Concurrent.js to exit immediately without waiting for workers to finish their tasks.
192
247
193
-
194
248
` ` ` ts
195
249
class Channel implements IChannel
196
250
` ` `
@@ -204,6 +258,7 @@ Used to send/receive messages to/from functions and methods (instance or static)
204
258
- ```ts
205
259
onmessage(handler: (name: string | number, ...data: unknown[]) => unknown): void
206
260
```
261
+
207
262
Sets the event handler for receiving a message. The handler should return a value if a reply is required for the message.
208
263
209
264
- ```ts
@@ -213,4 +268,5 @@ Used to send/receive messages to/from functions and methods (instance or static)
213
268
214
269
## License
215
270
216
- [MIT License](./LICENSE)
271
+ [MIT License](./LICENSE)
272
+
0 commit comments