Skip to content

Commit 999ca27

Browse files
authored
feat: Add idleThreads getter (#1055)
1 parent e2b1292 commit 999ca27

5 files changed

Lines changed: 47 additions & 0 deletions

File tree

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ For Node.js 24.x and higher.
5050
- [Property: `options` (readonly)](#property-options-readonly)
5151
- [Property: `runTime` (readonly)](#property-runtime-readonly)
5252
- [Property: `threads` (readonly)](#property-threads-readonly)
53+
- [Property: `idleThreads` (readonly)](#property-idlethreads-readonly)
5354
- [Property: `queueSize` (readonly)](#property-queuesize-readonly)
5455
- [Property: `needsDrain` (readonly)](#property-needsdrain-readonly)
5556
- [Property: `utilization` (readonly)](#property-utilization-readonly)
@@ -602,6 +603,11 @@ faster or equal to the given value.
602603

603604
An Array of the `Worker` instances used by this pool.
604605

606+
### Property: `idleThreads` (readonly)
607+
608+
The current number of ready (warmed up) Worker threads that are not running any
609+
task.
610+
605611
### Property: `queueSize` (readonly)
606612

607613
The current number of tasks waiting to be assigned to a Worker thread.

docs/docs/api-reference/api-overview.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ sidebar_position: 1
2020
| **Property: `options` (readonly)** | A copy of the options that are currently being used by this instance. |
2121
| **Property: `runTime` (readonly)** | A histogram summary object summarizing the collected run times of completed tasks. |
2222
| **Property: `threads` (readonly)** | An Array of the `Worker` instances used by this pool. |
23+
| **Property: `idleThreads` (readonly)** | The current number of ready (warmed up) Worker threads that are not running any task. |
2324
| **Property: `queueSize` (readonly)** | The current number of tasks waiting to be assigned to a Worker thread. |
2425
| **Property: `needsDrain` (readonly)** | Boolean value that specifies whether the capacity of the pool has been exceeded by the number of tasks submitted. |
2526
| **Property: `utilization` (readonly)** | A point-in-time ratio comparing the approximate total mean run time of completed tasks to the total runtime capacity of the pool. |

docs/docs/api-reference/property.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,11 @@ faster or equal to the given value.
6262

6363
An Array of the `Worker` instances used by this pool.
6464

65+
## Property: `idleThreads` (readonly)
66+
67+
The current number of ready (warmed up) Worker threads that are not running any
68+
task.
69+
6570
## Property: `queueSize` (readonly)
6671

6772
The current number of tasks waiting to be assigned to a Worker thread.

src/index.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -876,6 +876,14 @@ export default class Piscina<Exports extends Record<string, (payload: any) => an
876876
return ret;
877877
}
878878

879+
get idleThreads () : number {
880+
let count = 0;
881+
for (const workerInfo of this.#pool.workers.readyItems) {
882+
if (workerInfo.currentUsage() === 0) count++;
883+
}
884+
return count;
885+
}
886+
879887
get queueSize () : number {
880888
const pool = this.#pool;
881889
return Math.max((pool.taskQueue.size + pool.skipQueue.length) - pool.pendingCapacity(), 0);

test/thread-count.test.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,33 @@ test('conflicting min/max threads is error', () => {
9797
}), /options.minThreads and options.maxThreads must not conflict/);
9898
});
9999

100+
test('idleThreads reflects ready, unoccupied workers', async () => {
101+
const pool = new Piscina({
102+
filename: resolve(__dirname, 'fixtures/sleep.js'),
103+
minThreads: 2,
104+
maxThreads: 2,
105+
concurrentTasksPerWorker: 1
106+
});
107+
108+
// All minThreads workers are warmed and idle from the start.
109+
assert.strictEqual(pool.idleThreads, 2);
110+
111+
const first = pool.run({ time: 100 });
112+
// One worker is now busy.
113+
assert.strictEqual(pool.idleThreads, 1);
114+
115+
const second = pool.run({ time: 100 });
116+
// Both workers are busy.
117+
assert.strictEqual(pool.idleThreads, 0);
118+
119+
await Promise.all([first, second]);
120+
// Workers return to idle once tasks complete.
121+
assert.strictEqual(pool.idleThreads, 2);
122+
123+
await pool.destroy();
124+
assert.strictEqual(pool.idleThreads, 0);
125+
});
126+
100127
test('thread count should be 0 upon destruction', async () => {
101128
const pool = new Piscina({
102129
filename: resolve(__dirname, 'fixtures/eval.js'),

0 commit comments

Comments
 (0)