Skip to content

Commit

Permalink
feat(jest-cli, jest-config, @jest/core, jest-haste-map, @jest/reporte…
Browse files Browse the repository at this point in the history
…rs, jest-runner, jest-runtime, @jest/types): add `workerThreads` configuration option (#13939)
  • Loading branch information
mrazauskas committed Feb 22, 2023
1 parent 5858508 commit e2196ca
Show file tree
Hide file tree
Showing 15 changed files with 51 additions and 1 deletion.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -2,6 +2,7 @@

### Features

- `[jest-cli, jest-config, @jest/core, jest-haste-map, @jest/reporters, jest-runner, jest-runtime, @jest/types]` Add `workerThreads` configuration option to allow using [worker threads](https://nodejs.org/dist/latest/docs/api/worker_threads.html) for parallelization ([#13939](https://github.com/facebook/jest/pull/13939))
- `[jest-worker]` Add `start` method to worker farms ([#13937](https://github.com/facebook/jest/pull/13937))

### Fixes
Expand Down
10 changes: 10 additions & 0 deletions docs/CLI.md
Expand Up @@ -506,3 +506,13 @@ In most CI environments, this is automatically handled for you.
### `--watchman`

Whether to use [`watchman`](https://facebook.github.io/watchman/) for file crawling. Defaults to `true`. Disable using `--no-watchman`.

### `--workerThreads`

Whether to use [worker threads](https://nodejs.org/dist/latest/docs/api/worker_threads.html) for parallelization. [Child processes](https://nodejs.org/dist/latest/docs/api/child_process.html) are used by default.

:::caution

This is **experimental feature**. See the [`workerThreads` configuration option](Configuration.md#workerthreads) for more details.

:::
14 changes: 14 additions & 0 deletions docs/Configuration.md
Expand Up @@ -2375,3 +2375,17 @@ This option allows comments in `package.json`. Include the comment text as the v
}
}
```

### `workerThreads`

Default: `false`

Whether to use [worker threads](https://nodejs.org/dist/latest/docs/api/worker_threads.html) for parallelization. [Child processes](https://nodejs.org/dist/latest/docs/api/child_process.html) are used by default.

Using worker threads may help to improve [performance](https://github.com/nodejs/node/discussions/44264).

:::caution

This is **experimental feature**. Keep in mind that the worker threads use structured clone instead of `JSON.stringify()` to serialize messages. This means that built-in JavaScript objects as `BigInt`, `Map` or `Set` will get serialized properly. However extra properties set on `Error`, `Map` or `Set` will not be passed on through the serialization step. For more details see the article on [structured clone](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm).

:::
3 changes: 2 additions & 1 deletion e2e/__tests__/__snapshots__/showConfig.test.ts.snap
Expand Up @@ -138,7 +138,8 @@ exports[`--showConfig outputs config info and exits 1`] = `
"useStderr": false,
"watch": false,
"watchAll": false,
"watchman": true
"watchman": true,
"workerThreads": false
},
"version": "[version]"
}"
Expand Down
6 changes: 6 additions & 0 deletions packages/jest-cli/src/args.ts
Expand Up @@ -709,4 +709,10 @@ export const options: {[key: string]: Options} = {
'--no-watchman.',
type: 'boolean',
},
workerThreads: {
description:
'Whether to use worker threads for parallelization. Child processes ' +
'are used by default.',
type: 'boolean',
},
};
1 change: 1 addition & 0 deletions packages/jest-config/src/Defaults.ts
Expand Up @@ -88,6 +88,7 @@ const defaultOptions: Config.DefaultOptions = {
watch: false,
watchPathIgnorePatterns: [],
watchman: true,
workerThreads: false,
};

export default defaultOptions;
1 change: 1 addition & 0 deletions packages/jest-config/src/ValidConfig.ts
Expand Up @@ -186,6 +186,7 @@ export const initialOptions: Config.InitialOptions = {
],
watchman: true,
workerIdleMemoryLimit: multipleValidOptions(0.2, '50%'),
workerThreads: true,
};

export const initialProjectOptions: Config.InitialProjectOptions = {
Expand Down
1 change: 1 addition & 0 deletions packages/jest-config/src/index.ts
Expand Up @@ -140,6 +140,7 @@ const groupOptions = (
watchPlugins: options.watchPlugins,
watchman: options.watchman,
workerIdleMemoryLimit: options.workerIdleMemoryLimit,
workerThreads: options.workerThreads,
}),
projectConfig: Object.freeze({
automock: options.automock,
Expand Down
1 change: 1 addition & 0 deletions packages/jest-config/src/normalize.ts
Expand Up @@ -936,6 +936,7 @@ export default async function normalize(
case 'watch':
case 'watchAll':
case 'watchman':
case 'workerThreads':
value = oldOptions[key];
break;
case 'workerIdleMemoryLimit':
Expand Down
1 change: 1 addition & 0 deletions packages/jest-core/src/cli/index.ts
Expand Up @@ -157,6 +157,7 @@ const buildContextsAndHasteMaps = async (
resetCache: !config.cache,
watch: globalConfig.watch || globalConfig.watchAll,
watchman: globalConfig.watchman,
workerThreads: globalConfig.workerThreads,
});
hasteMapInstances[index] = hasteMapInstance;
return createContext(config, await hasteMapInstance.build());
Expand Down
4 changes: 4 additions & 0 deletions packages/jest-haste-map/src/index.ts
Expand Up @@ -79,6 +79,7 @@ type Options = {
throwOnModuleCollision?: boolean;
useWatchman?: boolean;
watch?: boolean;
workerThreads?: boolean;
};

type InternalOptions = {
Expand All @@ -103,6 +104,7 @@ type InternalOptions = {
throwOnModuleCollision: boolean;
useWatchman: boolean;
watch: boolean;
workerThreads?: boolean;
};

type Watcher = {
Expand Down Expand Up @@ -267,6 +269,7 @@ class HasteMap extends EventEmitter implements IHasteMap {
throwOnModuleCollision: !!options.throwOnModuleCollision,
useWatchman: options.useWatchman ?? true,
watch: !!options.watch,
workerThreads: options.workerThreads,
};
this._console = options.console || globalThis.console;

Expand Down Expand Up @@ -748,6 +751,7 @@ class HasteMap extends EventEmitter implements IHasteMap {
this._worker = {getSha1, worker};
} else {
this._worker = new Worker(require.resolve('./worker'), {
enableWorkerThreads: this._options.workerThreads,
exposedMethods: ['getSha1', 'worker'],
forkOptions: {serialization: 'json'},
maxRetries: 3,
Expand Down
1 change: 1 addition & 0 deletions packages/jest-reporters/src/CoverageReporter.ts
Expand Up @@ -147,6 +147,7 @@ export default class CoverageReporter extends BaseReporter {
worker = require('./CoverageWorker');
} else {
worker = new Worker(require.resolve('./CoverageWorker'), {
enableWorkerThreads: this._globalConfig.workerThreads,
exposedMethods: ['worker'],
forkOptions: {serialization: 'json'},
maxRetries: 2,
Expand Down
1 change: 1 addition & 0 deletions packages/jest-runner/src/index.ts
Expand Up @@ -105,6 +105,7 @@ export default class TestRunner extends EmittingTestRunner {
}

const worker = new Worker(require.resolve('./testWorker'), {
enableWorkerThreads: this._globalConfig.workerThreads,
exposedMethods: ['worker'],
forkOptions: {serialization: 'json', stdio: 'pipe'},
// The workerIdleMemoryLimit should've been converted to a number during
Expand Down
2 changes: 2 additions & 0 deletions packages/jest-runtime/src/index.ts
Expand Up @@ -79,6 +79,7 @@ type HasteMapOptions = {
resetCache: boolean;
watch?: boolean;
watchman: boolean;
workerThreads?: boolean;
};

interface InternalModuleOptions extends Required<CallerTransformOptions> {
Expand Down Expand Up @@ -370,6 +371,7 @@ export default class Runtime {
throwOnModuleCollision: config.haste.throwOnModuleCollision,
useWatchman: options?.watchman,
watch: options?.watch,
workerThreads: options?.workerThreads,
});
}

Expand Down
5 changes: 5 additions & 0 deletions packages/jest-types/src/Config.ts
Expand Up @@ -206,6 +206,7 @@ export type DefaultOptions = {
watch: boolean;
watchPathIgnorePatterns: Array<string>;
watchman: boolean;
workerThreads: boolean;
};

export type DisplayName = {
Expand Down Expand Up @@ -326,6 +327,7 @@ export type InitialOptions = Partial<{
watchman: boolean;
watchPlugins: Array<string | [string, Record<string, unknown>]>;
workerIdleMemoryLimit: number | string;
workerThreads: boolean;
}>;

export type SnapshotUpdateState = 'all' | 'new' | 'none';
Expand Down Expand Up @@ -419,6 +421,8 @@ export type GlobalConfig = {
config: Record<string, unknown>;
}> | null;
workerIdleMemoryLimit?: number;
// TODO: make non-optional in Jest 30
workerThreads?: boolean;
};

export type ProjectConfig = {
Expand Down Expand Up @@ -574,5 +578,6 @@ export type Argv = Arguments<
watchman: boolean;
watchPathIgnorePatterns: Array<string>;
workerIdleMemoryLimit: number | string;
workerThreads: boolean;
}>
>;

0 comments on commit e2196ca

Please sign in to comment.