Skip to content

Commit b1a27d4

Browse files
authored
feat(config): allow percentage value for workers option (#5982)
1 parent 50130bd commit b1a27d4

File tree

11 files changed

+174
-47
lines changed

11 files changed

+174
-47
lines changed

docs/config/index.md

+20-20
Original file line numberDiff line numberDiff line change
@@ -658,17 +658,17 @@ export default defineConfig({
658658

659659
##### poolOptions.threads.maxThreads<NonProjectOption />
660660

661-
- **Type:** `number`
661+
- **Type:** `number | string`
662662
- **Default:** _available CPUs_
663663

664-
Maximum number of threads. You can also use `VITEST_MAX_THREADS` environment variable.
664+
Maximum number or percentage of threads. You can also use `VITEST_MAX_THREADS` environment variable.
665665

666666
##### poolOptions.threads.minThreads<NonProjectOption />
667667

668-
- **Type:** `number`
668+
- **Type:** `number | string`
669669
- **Default:** _available CPUs_
670670

671-
Minimum number of threads. You can also use `VITEST_MIN_THREADS` environment variable.
671+
Minimum number or percentage of threads. You can also use `VITEST_MIN_THREADS` environment variable.
672672

673673
##### poolOptions.threads.singleThread
674674

@@ -730,17 +730,17 @@ export default defineConfig({
730730

731731
##### poolOptions.forks.maxForks<NonProjectOption />
732732

733-
- **Type:** `number`
733+
- **Type:** `number | string`
734734
- **Default:** _available CPUs_
735735

736-
Maximum number of forks.
736+
Maximum number or percentage of forks.
737737

738738
##### poolOptions.forks.minForks<NonProjectOption />
739739

740-
- **Type:** `number`
740+
- **Type:** `number | string`
741741
- **Default:** _available CPUs_
742742

743-
Minimum number of forks.
743+
Minimum number or percentage of forks.
744744

745745
##### poolOptions.forks.isolate
746746

@@ -793,17 +793,17 @@ export default defineConfig({
793793

794794
##### poolOptions.vmThreads.maxThreads<NonProjectOption />
795795

796-
- **Type:** `number`
796+
- **Type:** `number | string`
797797
- **Default:** _available CPUs_
798798

799-
Maximum number of threads. You can also use `VITEST_MAX_THREADS` environment variable.
799+
Maximum number or percentage of threads. You can also use `VITEST_MAX_THREADS` environment variable.
800800

801801
##### poolOptions.vmThreads.minThreads<NonProjectOption />
802802

803-
- **Type:** `number`
803+
- **Type:** `number | string`
804804
- **Default:** _available CPUs_
805805

806-
Minimum number of threads. You can also use `VITEST_MIN_THREADS` environment variable.
806+
Minimum number or percentage of threads. You can also use `VITEST_MIN_THREADS` environment variable.
807807

808808
##### poolOptions.vmThreads.memoryLimit<NonProjectOption />
809809

@@ -874,17 +874,17 @@ export default defineConfig({
874874

875875
##### poolOptions.vmForks.maxForks<NonProjectOption />
876876

877-
- **Type:** `number`
877+
- **Type:** `number | string`
878878
- **Default:** _available CPUs_
879879

880-
Maximum number of threads. You can also use `VITEST_MAX_FORKS` environment variable.
880+
Maximum number or percentage of threads. You can also use `VITEST_MAX_FORKS` environment variable.
881881

882882
##### poolOptions.vmForks.minForks<NonProjectOption />
883883

884-
- **Type:** `number`
884+
- **Type:** `number | string`
885885
- **Default:** _available CPUs_
886886

887-
Minimum number of threads. You can also use `VITEST_MIN_FORKS` environment variable.
887+
Minimum number or percentage of threads. You can also use `VITEST_MIN_FORKS` environment variable.
888888

889889
##### poolOptions.vmForks.memoryLimit<NonProjectOption />
890890

@@ -918,15 +918,15 @@ This option doesn't affect tests running in the same file. If you want to run th
918918

919919
### maxWorkers<NonProjectOption /> {#maxworkers}
920920

921-
- **Type:** `number`
921+
- **Type:** `number | string`
922922

923-
Maximum number of workers to run tests in. `poolOptions.{threads,vmThreads}.maxThreads`/`poolOptions.forks.maxForks` has higher priority.
923+
Maximum number or percentage of workers to run tests in. `poolOptions.{threads,vmThreads}.maxThreads`/`poolOptions.forks.maxForks` has higher priority.
924924

925925
### minWorkers<NonProjectOption /> {#minworkers}
926926

927-
- **Type:** `number`
927+
- **Type:** `number | string`
928928

929-
Minimum number of workers to run tests in. `poolOptions.{threads,vmThreads}.minThreads`/`poolOptions.forks.minForks` has higher priority.
929+
Minimum number or percentage of workers to run tests in. `poolOptions.{threads,vmThreads}.minThreads`/`poolOptions.forks.minForks` has higher priority.
930930

931931
### testTimeout
932932

docs/guide/cli-table.md

+10-10
Original file line numberDiff line numberDiff line change
@@ -61,27 +61,27 @@
6161
| `--pool <pool>` | Specify pool, if not running in the browser (default: `threads`) |
6262
| `--poolOptions.threads.isolate` | Isolate tests in threads pool (default: `true`) |
6363
| `--poolOptions.threads.singleThread` | Run tests inside a single thread (default: `false`) |
64-
| `--poolOptions.threads.maxThreads <workers>` | Maximum number of threads to run tests in |
65-
| `--poolOptions.threads.minThreads <workers>` | Minimum number of threads to run tests in |
64+
| `--poolOptions.threads.maxThreads <workers>` | Maximum number or percentage of threads to run tests in |
65+
| `--poolOptions.threads.minThreads <workers>` | Minimum number or percentage of threads to run tests in |
6666
| `--poolOptions.threads.useAtomics` | Use Atomics to synchronize threads. This can improve performance in some cases, but might cause segfault in older Node versions (default: `false`) |
6767
| `--poolOptions.vmThreads.isolate` | Isolate tests in threads pool (default: `true`) |
6868
| `--poolOptions.vmThreads.singleThread` | Run tests inside a single thread (default: `false`) |
69-
| `--poolOptions.vmThreads.maxThreads <workers>` | Maximum number of threads to run tests in |
70-
| `--poolOptions.vmThreads.minThreads <workers>` | Minimum number of threads to run tests in |
69+
| `--poolOptions.vmThreads.maxThreads <workers>` | Maximum number or percentage of threads to run tests in |
70+
| `--poolOptions.vmThreads.minThreads <workers>` | Minimum number or percentage of threads to run tests in |
7171
| `--poolOptions.vmThreads.useAtomics` | Use Atomics to synchronize threads. This can improve performance in some cases, but might cause segfault in older Node versions (default: `false`) |
7272
| `--poolOptions.vmThreads.memoryLimit <limit>` | Memory limit for VM threads pool. If you see memory leaks, try to tinker this value. |
7373
| `--poolOptions.forks.isolate` | Isolate tests in forks pool (default: `true`) |
7474
| `--poolOptions.forks.singleFork` | Run tests inside a single child_process (default: `false`) |
75-
| `--poolOptions.forks.maxForks <workers>` | Maximum number of processes to run tests in |
76-
| `--poolOptions.forks.minForks <workers>` | Minimum number of processes to run tests in |
75+
| `--poolOptions.forks.maxForks <workers>` | Maximum number or percentage of processes to run tests in |
76+
| `--poolOptions.forks.minForks <workers>` | Minimum number or percentage of processes to run tests in |
7777
| `--poolOptions.vmForks.isolate` | Isolate tests in forks pool (default: `true`) |
7878
| `--poolOptions.vmForks.singleFork` | Run tests inside a single child_process (default: `false`) |
79-
| `--poolOptions.vmForks.maxForks <workers>` | Maximum number of processes to run tests in |
80-
| `--poolOptions.vmForks.minForks <workers>` | Minimum number of processes to run tests in |
79+
| `--poolOptions.vmForks.maxForks <workers>` | Maximum number or percentage of processes to run tests in |
80+
| `--poolOptions.vmForks.minForks <workers>` | Minimum number or percentage of processes to run tests in |
8181
| `--poolOptions.vmForks.memoryLimit <limit>` | Memory limit for VM forks pool. If you see memory leaks, try to tinker this value. |
8282
| `--fileParallelism` | Should all test files run in parallel. Use `--no-file-parallelism` to disable (default: `true`) |
83-
| `--maxWorkers <workers>` | Maximum number of workers to run tests in |
84-
| `--minWorkers <workers>` | Minimum number of workers to run tests in |
83+
| `--maxWorkers <workers>` | Maximum number or percentage of workers to run tests in |
84+
| `--minWorkers <workers>` | Minimum number or percentage of workers to run tests in |
8585
| `--environment <name>` | Specify runner environment, if not running in the browser (default: `node`) |
8686
| `--passWithNoTests` | Pass when no tests are found |
8787
| `--logHeapUsage` | Show the size of heap for each test when running in node |

packages/vitest/rollup.config.js

+1
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ const external = [
6767
'worker_threads',
6868
'node:worker_threads',
6969
'node:fs',
70+
'node:os',
7071
'node:stream',
7172
'node:vm',
7273
'inspector',

packages/vitest/src/node/cli/cli-config.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,11 @@ const poolThreadsCommands: CLIOptions<ThreadsOptions & WorkerContextOptions> = {
6262
description: 'Run tests inside a single thread (default: `false`)',
6363
},
6464
maxThreads: {
65-
description: 'Maximum number of threads to run tests in',
65+
description: 'Maximum number or percentage of threads to run tests in',
6666
argument: '<workers>',
6767
},
6868
minThreads: {
69-
description: 'Minimum number of threads to run tests in',
69+
description: 'Minimum number or percentage of threads to run tests in',
7070
argument: '<workers>',
7171
},
7272
useAtomics: {
@@ -84,11 +84,11 @@ const poolForksCommands: CLIOptions<ForksOptions & WorkerContextOptions> = {
8484
description: 'Run tests inside a single child_process (default: `false`)',
8585
},
8686
maxForks: {
87-
description: 'Maximum number of processes to run tests in',
87+
description: 'Maximum number or percentage of processes to run tests in',
8888
argument: '<workers>',
8989
},
9090
minForks: {
91-
description: 'Minimum number of processes to run tests in',
91+
description: 'Minimum number or percentage of processes to run tests in',
9292
argument: '<workers>',
9393
},
9494
execArgv: null,

packages/vitest/src/node/config.ts

+39-3
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ import {
1616
} from '../constants'
1717
import { benchmarkConfigDefaults, configDefaults } from '../defaults'
1818
import { isCI, stdProvider, toArray } from '../utils'
19-
import type { BuiltinPool } from '../types/pool-options'
19+
import type { BuiltinPool, ForksOptions, PoolOptions, ThreadsOptions } from '../types/pool-options'
20+
import { getWorkersCountByPercentage } from '../utils/workers'
2021
import { VitestCache } from './cache'
2122
import { BaseSequencer } from './sequencers/BaseSequencer'
2223
import { RandomSequencer } from './sequencers/RandomSequencer'
@@ -97,6 +98,15 @@ export function resolveApiServerConfig<Options extends ApiConfig & UserConfig>(
9798
return api
9899
}
99100

101+
function resolveInlineWorkerOption(value: string | number): number {
102+
if (typeof value === 'string' && value.trim().endsWith('%')) {
103+
return getWorkersCountByPercentage(value)
104+
}
105+
else {
106+
return Number(value)
107+
}
108+
}
109+
100110
export function resolveConfig(
101111
mode: VitestRunMode,
102112
options: UserConfig,
@@ -176,11 +186,11 @@ export function resolveConfig(
176186
}
177187

178188
if (resolved.maxWorkers) {
179-
resolved.maxWorkers = Number(resolved.maxWorkers)
189+
resolved.maxWorkers = resolveInlineWorkerOption(resolved.maxWorkers)
180190
}
181191

182192
if (resolved.minWorkers) {
183-
resolved.minWorkers = Number(resolved.minWorkers)
193+
resolved.minWorkers = resolveInlineWorkerOption(resolved.minWorkers)
184194
}
185195

186196
resolved.browser ??= {} as any
@@ -436,6 +446,32 @@ export function resolveConfig(
436446
}
437447
}
438448

449+
const poolThreadsOptions = [
450+
['threads', 'minThreads'],
451+
['threads', 'maxThreads'],
452+
['vmThreads', 'minThreads'],
453+
['vmThreads', 'maxThreads'],
454+
] as const satisfies [keyof PoolOptions, keyof ThreadsOptions][]
455+
456+
for (const [poolOptionKey, workerOptionKey] of poolThreadsOptions) {
457+
if (resolved.poolOptions?.[poolOptionKey]?.[workerOptionKey]) {
458+
resolved.poolOptions[poolOptionKey]![workerOptionKey] = resolveInlineWorkerOption(resolved.poolOptions[poolOptionKey]![workerOptionKey]!)
459+
}
460+
}
461+
462+
const poolForksOptions = [
463+
['forks', 'minForks'],
464+
['forks', 'maxForks'],
465+
['vmForks', 'minForks'],
466+
['vmForks', 'maxForks'],
467+
] as const satisfies [keyof PoolOptions, keyof ForksOptions][]
468+
469+
for (const [poolOptionKey, workerOptionKey] of poolForksOptions) {
470+
if (resolved.poolOptions?.[poolOptionKey]?.[workerOptionKey]) {
471+
resolved.poolOptions[poolOptionKey]![workerOptionKey] = resolveInlineWorkerOption(resolved.poolOptions[poolOptionKey]![workerOptionKey]!)
472+
}
473+
}
474+
439475
if (resolved.workspace) {
440476
// if passed down from the CLI and it's relative, resolve relative to CWD
441477
resolved.workspace

packages/vitest/src/types/config.ts

+9-6
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import type { SnapshotStateOptions } from './snapshot'
1717
import type { Arrayable, ParsedStack } from './general'
1818
import type { BenchmarkUserOptions } from './benchmark'
1919
import type { BrowserConfigOptions, ResolvedBrowserOptions } from './browser'
20-
import type { Pool, PoolOptions } from './pool-options'
20+
import type { Pool, PoolOptions, ResolvedPoolOptions } from './pool-options'
2121

2222
export type { BrowserScript, BrowserConfigOptions } from './browser'
2323
export type { SequenceHooks, SequenceSetupFiles } from '@vitest/runner'
@@ -343,13 +343,13 @@ export interface InlineConfig {
343343
poolOptions?: PoolOptions
344344

345345
/**
346-
* Maximum number of workers to run tests in. `poolOptions.{threads,vmThreads}.maxThreads`/`poolOptions.forks.maxForks` has higher priority.
346+
* Maximum number or percentage of workers to run tests in. `poolOptions.{threads,vmThreads}.maxThreads`/`poolOptions.forks.maxForks` has higher priority.
347347
*/
348-
maxWorkers?: number
348+
maxWorkers?: number | string
349349
/**
350-
* Minimum number of workers to run tests in. `poolOptions.{threads,vmThreads}.minThreads`/`poolOptions.forks.minForks` has higher priority.
350+
* Minimum number or percentage of workers to run tests in. `poolOptions.{threads,vmThreads}.minThreads`/`poolOptions.forks.minForks` has higher priority.
351351
*/
352-
minWorkers?: number
352+
minWorkers?: number | string
353353

354354
/**
355355
* Should all test files run in parallel. Doesn't affect tests running in the same file.
@@ -969,7 +969,7 @@ export interface ResolvedConfig
969969

970970
browser: ResolvedBrowserOptions
971971
pool: Pool
972-
poolOptions?: PoolOptions
972+
poolOptions?: ResolvedPoolOptions
973973

974974
reporters: (InlineReporter | ReporterWithOptions)[]
975975

@@ -1009,6 +1009,9 @@ export interface ResolvedConfig
10091009
enabled: boolean
10101010
}
10111011
runner?: string
1012+
1013+
maxWorkers: number
1014+
minWorkers: number
10121015
}
10131016

10141017
export type ProjectConfig = Omit<

packages/vitest/src/types/pool-options.ts

+21-4
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,19 @@ export interface PoolOptions extends Record<string, unknown> {
4242
vmForks?: ForksOptions & VmOptions
4343
}
4444

45+
export interface ResolvedPoolOptions extends PoolOptions {
46+
threads?: ResolvedThreadsOptions & WorkerContextOptions
47+
forks?: ResolvedForksOptions & WorkerContextOptions
48+
vmThreads?: ResolvedThreadsOptions & VmOptions
49+
vmForks?: ResolvedForksOptions & VmOptions
50+
}
51+
4552
export interface ThreadsOptions {
4653
/** Minimum amount of threads to use */
47-
minThreads?: number
54+
minThreads?: number | string
4855

4956
/** Maximum amount of threads to use */
50-
maxThreads?: number
57+
maxThreads?: number | string
5158

5259
/**
5360
* Run tests inside a single thread.
@@ -66,12 +73,17 @@ export interface ThreadsOptions {
6673
useAtomics?: boolean
6774
}
6875

76+
export interface ResolvedThreadsOptions extends ThreadsOptions {
77+
minThreads?: number
78+
maxThreads?: number
79+
}
80+
6981
export interface ForksOptions {
7082
/** Minimum amount of child processes to use */
71-
minForks?: number
83+
minForks?: number | string
7284

7385
/** Maximum amount of child processes to use */
74-
maxForks?: number
86+
maxForks?: number | string
7587

7688
/**
7789
* Run tests inside a single fork.
@@ -81,6 +93,11 @@ export interface ForksOptions {
8193
singleFork?: boolean
8294
}
8395

96+
export interface ResolvedForksOptions extends ForksOptions {
97+
minForks?: number
98+
maxForks?: number
99+
}
100+
84101
export interface WorkerContextOptions {
85102
/**
86103
* Isolate test environment by recycling `worker_threads` or `child_process` after each test

packages/vitest/src/utils/workers.ts

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import os from 'node:os'
2+
3+
export function getWorkersCountByPercentage(percent: string) {
4+
const maxWorkersCount = os.availableParallelism?.() ?? os.cpus().length
5+
const workersCountByPercentage = Math.round((Number.parseInt(percent) / 100) * maxWorkersCount)
6+
7+
return Math.max(1, Math.min(maxWorkersCount, workersCountByPercentage))
8+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { expect, test } from 'vitest'
2+
3+
test('it works', () => {
4+
expect(true).toBe(true)
5+
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export default {}

0 commit comments

Comments
 (0)