knitting 0.1.60 → 0.1.61
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/BROWSER.md +134 -0
- package/README.md +93 -6
- package/knitting.browser.d.ts +6 -0
- package/knitting.browser.js +1 -0
- package/package.json +11 -2
- package/prebuilds/darwin-arm64-node-127/knitting_buffer_pointer.node +0 -0
- package/prebuilds/darwin-arm64-node-127/knitting_shared_memory.node +0 -0
- package/prebuilds/darwin-arm64-node-127/knitting_shm.node +0 -0
- package/prebuilds/darwin-arm64-node-137/knitting_buffer_pointer.node +0 -0
- package/prebuilds/darwin-arm64-node-137/knitting_shared_memory.node +0 -0
- package/prebuilds/darwin-arm64-node-137/knitting_shm.node +0 -0
- package/prebuilds/win32-x64/knitting_windows_shared_memory.dll +0 -0
- package/prebuilds/win32-x64-node-127/knitting_buffer_pointer.node +0 -0
- package/prebuilds/win32-x64-node-127/knitting_shared_memory.node +0 -0
- package/prebuilds/win32-x64-node-127/knitting_shm.node +0 -0
- package/prebuilds/win32-x64-node-137/knitting_buffer_pointer.node +0 -0
- package/prebuilds/win32-x64-node-137/knitting_shared_memory.node +0 -0
- package/prebuilds/win32-x64-node-137/knitting_shm.node +0 -0
- package/src/api.js +127 -22
- package/src/common/runtime.d.ts +2 -1
- package/src/common/runtime.js +8 -1
- package/src/memory/lock.d.ts +26 -1
- package/src/memory/lock.js +212 -4
- package/src/memory/payloadCodec.js +2 -6
- package/src/memory/regionRegistry.d.ts +1 -3
- package/src/memory/regionRegistry.js +16 -14
- package/src/permission/protocol.js +5 -1
- package/src/runtime/dispatcher.js +9 -0
- package/src/runtime/pool.d.ts +114 -3
- package/src/runtime/pool.js +209 -63
- package/src/runtime/process-worker.d.ts +2 -12
- package/src/runtime/process-worker.js +69 -113
- package/src/runtime/tx-queue.d.ts +15 -1
- package/src/runtime/tx-queue.js +52 -15
- package/src/runtime/worker-common.d.ts +13 -0
- package/src/runtime/worker-common.js +102 -0
- package/src/types.d.ts +41 -3
- package/src/worker/loop.js +27 -5
- package/src/worker/rx-queue.d.ts +11 -1
- package/src/worker/rx-queue.js +4 -1
- package/src/worker/timers.d.ts +8 -1
- package/src/worker/timers.js +20 -17
package/src/worker/rx-queue.d.ts
CHANGED
|
@@ -9,9 +9,19 @@ type ArgumentsForCreateWorkerQueue = {
|
|
|
9
9
|
borrowReturnedBufferReferences?: boolean;
|
|
10
10
|
hasAborted?: (signal: number) => boolean;
|
|
11
11
|
now?: () => number;
|
|
12
|
+
/**
|
|
13
|
+
* Work-stealing discipline: only claim when this worker has nothing left to
|
|
14
|
+
* run. Without it a worker keeps claiming whole regions on top of a backlog
|
|
15
|
+
* it has not started, which is exactly the hoarding stealing exists to
|
|
16
|
+
* prevent — the queued tasks would be better taken by an idle peer.
|
|
17
|
+
*
|
|
18
|
+
* Off for the classic per-lane path, where the host has already assigned
|
|
19
|
+
* these tasks to this lane and batching them is a win.
|
|
20
|
+
*/
|
|
21
|
+
stealing?: boolean;
|
|
12
22
|
};
|
|
13
23
|
export type CreateWorkerRxQueue = ReturnType<typeof createWorkerRxQueue>;
|
|
14
|
-
export declare const createWorkerRxQueue: ({ listOfFunctions, workerOptions, lock, returnLock, borrowReturnedBufferReferences, hasAborted, now, }: ArgumentsForCreateWorkerQueue) => {
|
|
24
|
+
export declare const createWorkerRxQueue: ({ listOfFunctions, workerOptions, lock, returnLock, borrowReturnedBufferReferences, hasAborted, now, stealing, }: ArgumentsForCreateWorkerQueue) => {
|
|
15
25
|
hasCompleted: () => boolean;
|
|
16
26
|
hasPending: () => boolean;
|
|
17
27
|
writeBatch: (max: number) => number;
|
package/src/worker/rx-queue.js
CHANGED
|
@@ -2,7 +2,7 @@ import RingQueue from "../ipc/tools/ring-queue.js";
|
|
|
2
2
|
import { attachPayloadTransportFinalizer, runTaskFinalizers, TaskFlag, TaskIndex, } from "../memory/lock.js";
|
|
3
3
|
import { composeWorkerRunner } from "./composable-runners.js";
|
|
4
4
|
import { BUFFER_REFERENCE_RETURN_RELEASE_TOKEN } from "../connections/buffer-reference.js";
|
|
5
|
-
export const createWorkerRxQueue = ({ listOfFunctions, workerOptions, lock, returnLock, borrowReturnedBufferReferences, hasAborted, now, }) => {
|
|
5
|
+
export const createWorkerRxQueue = ({ listOfFunctions, workerOptions, lock, returnLock, borrowReturnedBufferReferences, hasAborted, now, stealing, }) => {
|
|
6
6
|
const PLACE_HOLDER = (_) => {
|
|
7
7
|
throw ("UNREACHABLE FROM PLACE HOLDER (thread)");
|
|
8
8
|
};
|
|
@@ -71,6 +71,9 @@ export const createWorkerRxQueue = ({ listOfFunctions, workerOptions, lock, retu
|
|
|
71
71
|
const { decode, resolved } = lock;
|
|
72
72
|
const resolvedShift = () => resolved.shiftNoClear();
|
|
73
73
|
const enqueueLock = () => {
|
|
74
|
+
// Steal only when idle: leaving work unclaimed lets a free peer take it.
|
|
75
|
+
if (stealing && toWork.size !== 0)
|
|
76
|
+
return false;
|
|
74
77
|
if (!decode())
|
|
75
78
|
return false;
|
|
76
79
|
let task = resolvedShift();
|
package/src/worker/timers.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ type PauseOptions = {
|
|
|
4
4
|
export type NativeWaitU32 = (buffer: ArrayBuffer | SharedArrayBuffer, byteOffset: number, expected: number, timeoutMs?: number) => unknown;
|
|
5
5
|
export declare const whilePausing: ({ pauseInNanoseconds }: PauseOptions) => () => void;
|
|
6
6
|
export declare const pauseGeneric: () => void;
|
|
7
|
-
export declare const sleepUntilChanged: ({ at, opView, pauseInNanoseconds, rxStatus, txStatus, enqueueLock, write, nativeWaitU32, useSharedMemoryWait, }: {
|
|
7
|
+
export declare const sleepUntilChanged: ({ at, opView, pauseInNanoseconds, rxStatus, txStatus, enqueueLock, write, nativeWaitU32, useSharedMemoryWait, flushBeforeClaim, }: {
|
|
8
8
|
opView: Int32Array;
|
|
9
9
|
rxStatus: Int32Array;
|
|
10
10
|
txStatus: Int32Array;
|
|
@@ -14,5 +14,12 @@ export declare const sleepUntilChanged: ({ at, opView, pauseInNanoseconds, rxSta
|
|
|
14
14
|
write?: () => number | boolean;
|
|
15
15
|
nativeWaitU32?: NativeWaitU32;
|
|
16
16
|
useSharedMemoryWait?: boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Stealing only: write results back before attempting to claim more work.
|
|
19
|
+
* A claim can spin waiting for a peer to withdraw its intent, so claiming
|
|
20
|
+
* first puts arbitration latency in front of a finished response. Measured
|
|
21
|
+
* to hurt the per-lane path, so it stays off by default.
|
|
22
|
+
*/
|
|
23
|
+
flushBeforeClaim?: boolean;
|
|
17
24
|
}) => (value: number, spinMicroseconds: number, parkMs?: number) => void;
|
|
18
25
|
export {};
|
package/src/worker/timers.js
CHANGED
|
@@ -30,7 +30,9 @@ const a_load = Atomics.load;
|
|
|
30
30
|
const a_store = Atomics.store;
|
|
31
31
|
const a_wait = typeof Atomics.wait === "function" ? Atomics.wait : undefined;
|
|
32
32
|
const p_now = performance.now.bind(performance);
|
|
33
|
-
|
|
33
|
+
// `SharedArrayBuffer` is undeclared on pages that are not cross-origin
|
|
34
|
+
// isolated, and this module has to load anyway so the pool can report why.
|
|
35
|
+
const waitFallbackView = a_wait === undefined || typeof SharedArrayBuffer !== "function"
|
|
34
36
|
? undefined
|
|
35
37
|
: new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT));
|
|
36
38
|
const a_pause = "pause" in Atomics
|
|
@@ -59,26 +61,27 @@ export const whilePausing = ({ pauseInNanoseconds }) => {
|
|
|
59
61
|
return () => a_pause(forNanoseconds);
|
|
60
62
|
};
|
|
61
63
|
export const pauseGeneric = whilePausing({});
|
|
62
|
-
export const sleepUntilChanged = ({ at, opView, pauseInNanoseconds, rxStatus, txStatus, enqueueLock, write, nativeWaitU32, useSharedMemoryWait = true, }) => {
|
|
64
|
+
export const sleepUntilChanged = ({ at, opView, pauseInNanoseconds, rxStatus, txStatus, enqueueLock, write, nativeWaitU32, useSharedMemoryWait = true, flushBeforeClaim = false, }) => {
|
|
63
65
|
const pause = pauseInNanoseconds === undefined
|
|
64
66
|
? pauseGeneric
|
|
65
67
|
: whilePausing({ pauseInNanoseconds });
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
if (
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
if (wrote > 0)
|
|
74
|
-
progressed = true;
|
|
75
|
-
}
|
|
76
|
-
else if (wrote === true) {
|
|
77
|
-
progressed = true;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
return progressed;
|
|
68
|
+
const flushWrite = () => {
|
|
69
|
+
if (!write)
|
|
70
|
+
return false;
|
|
71
|
+
const wrote = write();
|
|
72
|
+
if (typeof wrote === "number")
|
|
73
|
+
return wrote > 0;
|
|
74
|
+
return wrote === true;
|
|
81
75
|
};
|
|
76
|
+
const tryProgress = flushBeforeClaim
|
|
77
|
+
? () => {
|
|
78
|
+
const wrote = flushWrite();
|
|
79
|
+
return enqueueLock() || wrote;
|
|
80
|
+
}
|
|
81
|
+
: () => {
|
|
82
|
+
const claimed = enqueueLock();
|
|
83
|
+
return flushWrite() || claimed;
|
|
84
|
+
};
|
|
82
85
|
return (value, spinMicroseconds, parkMs) => {
|
|
83
86
|
const until = p_now() + (spinMicroseconds / 1000);
|
|
84
87
|
maybeGc();
|