Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix!: change default pool to 'forks' #5047

Merged
merged 1 commit into from
May 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/config/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -586,7 +586,7 @@ By providing an object instead of a string you can define individual outputs whe
### pool<NonProjectOption /> <Badge type="info">1.0.0+</Badge> {#pool}

- **Type:** `'threads' | 'forks' | 'vmThreads' | 'vmForks'`
- **Default:** `'threads'`
- **Default:** `'forks'` (in v1 `'threads'`)
- **CLI:** `--pool=threads`

Pool used to run tests in.
Expand Down
38 changes: 29 additions & 9 deletions docs/guide/common-errors.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,8 @@ This error can happen when NodeJS's `fetch` is used with default [`pool: 'thread

As work-around you can switch to [`pool: 'forks'`](/config/#forks) or [`pool: 'vmForks'`](/config/#vmforks).

Specify `pool` in your configuration file:

```ts
::: code-group
```ts [vitest.config.js]
import { defineConfig } from 'vitest/config'

export default defineConfig({
Expand All @@ -76,12 +75,33 @@ export default defineConfig({
},
})
```
```bash [CLI]
vitest --pool=forks
```
:::

Or in your `package.json` scripts:
## Segfaults and native code errors

```diff
scripts: {
- "test": "vitest"
+ "test": "vitest --pool=forks"
}
Running [native NodeJS modules](https://nodejs.org/api/addons.html) in `pool: 'threads'` can run into cryptic errors coming from the native code.

- `Segmentation fault (core dumped)`
- `thread '<unnamed>' panicked at 'assertion failed`
- `Abort trap: 6`
- `internal error: entered unreachable code`

In these cases the native module is likely not built to be multi-thread safe. As work-around, you can switch to `pool: 'forks'` which runs the test cases in multiple `node:child_process` instead of multiple `node:worker_threads`.

::: code-group
```ts [vitest.config.js]
import { defineConfig } from 'vitest/config'

export default defineConfig({
test: {
pool: 'forks',
},
})
```
```bash [CLI]
vitest --pool=forks
```
:::
23 changes: 23 additions & 0 deletions docs/guide/improving-performance.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Improving Performance

## Test isolation

By default Vitest runs every test file in an isolated environment based on the [pool](/config/#pool):

- `threads` pool runs every test file in a separate [`Worker`](https://nodejs.org/api/worker_threads.html#class-worker)
Expand Down Expand Up @@ -49,3 +51,24 @@ export default defineConfig({
})
```
:::

## Pool

By default Vitest runs tests in `pool: 'forks'`. While `'forks'` pool is better for compatibility issues ([hanging process](/guide/common-errors.html#failed-to-terminate-worker) and [segfaults](/guide/common-errors.html#segfaults-and-native-code-errors)), it may be slightly slower than `pool: 'threads'` in larger projects.

You can try to improve test run time by switching `pool` option in configuration:

::: code-group
```bash [CLI]
vitest --pool=threads
```
```ts [vitest.config.js]
import { defineConfig } from 'vitest/config'

export default defineConfig({
test: {
pool: 'threads',
},
})
```
:::
2 changes: 1 addition & 1 deletion packages/vitest/src/defaults.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ const config = {
watch: !isCI,
globals: false,
environment: 'node' as const,
pool: 'threads' as const,
pool: 'forks' as const,
clearMocks: false,
restoreMocks: false,
mockReset: false,
Expand Down
4 changes: 2 additions & 2 deletions test/browser/vitest.config.unit.mts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ export default defineConfig({
test: {
include: ['specs/**/*.{spec,test}.ts'],
poolOptions: {
threads: {
singleThread: true,
forks: {
singleFork: true,
},
},
hookTimeout: process.env.CI ? 120_000 : 10_000,
Expand Down
11 changes: 4 additions & 7 deletions test/config/test/chai-config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ describe('truncateThreshold', () => {
ok 6 - test-each-title.test.ts > [ 'one', 'two', 'three', 'four', …(1) ]
ok 7 - test-each-title.test.ts > { one: 1, two: 2, three: 3 }
ok 8 - test-each-title.test.ts > { one: 1, two: 2, three: 3, four: 4 }
ok 9 - test-each-title.test.ts > { one: 1, two: 2, three: 3, …(2) }
"
ok 9 - test-each-title.test.ts > { one: 1, two: 2, three: 3, …(2) }"
`)
expect(result.exitCode).toBe(0)
})
Expand All @@ -43,8 +42,7 @@ describe('truncateThreshold', () => {
ok 6 - test-each-title.test.ts > [ 'one', 'two', 'three', 'four', …(1) ]
ok 7 - test-each-title.test.ts > { one: 1, two: 2, three: 3 }
ok 8 - test-each-title.test.ts > { one: 1, two: 2, three: 3, four: 4 }
ok 9 - test-each-title.test.ts > { one: 1, two: 2, three: 3, …(2) }
"
ok 9 - test-each-title.test.ts > { one: 1, two: 2, three: 3, …(2) }"
`)
expect(result.exitCode).toBe(0)
})
Expand All @@ -68,14 +66,13 @@ describe('truncateThreshold', () => {
ok 6 - test-each-title.test.ts > [ 'one', 'two', 'three', 'four', 'five' ]
ok 7 - test-each-title.test.ts > { one: 1, two: 2, three: 3 }
ok 8 - test-each-title.test.ts > { one: 1, two: 2, three: 3, four: 4 }
ok 9 - test-each-title.test.ts > { one: 1, two: 2, three: 3, four: 4, five: 5 }
"
ok 9 - test-each-title.test.ts > { one: 1, two: 2, three: 3, four: 4, five: 5 }"
`)
expect(result.exitCode).toBe(0)
})
})

function cleanOutput(output: string) {
// remove non-deterministic output
return output.replaceAll(/\s*# time=.*/g, '')
return output.replaceAll(/\s*# time=.*/g, '').trim()
}
2 changes: 1 addition & 1 deletion test/config/test/failures.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,6 @@ test('boolean flag 100 should not crash CLI', async () => {

test('nextTick cannot be mocked inside child_process', async () => {
const { stderr } = await runVitest({
pool: 'forks',
fakeTimers: { toFake: ['nextTick'] },
include: ['./fake-timers.test.ts'],
})
Expand All @@ -154,6 +153,7 @@ test('nextTick cannot be mocked inside child_process', async () => {

test('nextTick can be mocked inside worker_threads', async () => {
const { stderr } = await runVitest({
pool: 'threads',
fakeTimers: { toFake: ['nextTick'] },
include: ['./fixtures/test/fake-timers.test.ts'],
})
Expand Down
7 changes: 2 additions & 5 deletions test/watch/vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,10 @@ export default defineConfig({
testTimeout: process.env.CI ? 60_000 : 10_000,

// Test cases may have side effects, e.g. files under fixtures/ are modified on the fly to trigger file watchers
poolOptions: {
forks: { singleFork: true },
threads: { singleThread: true },
vmThreads: { singleThread: true },
},
fileParallelism: false,

// TODO: Fix flakiness and remove
allowOnly: true,
bail: 1,
},
})