feat(core): run parallel based on the number of cpu cores (#31011)

This commit is contained in:
Yiheng 2025-05-13 22:19:16 +08:00 committed by GitHub
parent 3f5fd896a1
commit cd59a6678e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 66 additions and 4 deletions

View File

@ -11,6 +11,12 @@ If you want to increase the number of processes running tasks to, say, 5 (by def
npx nx build myapp --parallel=5 npx nx build myapp --parallel=5
``` ```
You can also set parallel based on the percentage of the number of logical CPUs.
```shell
npx nx build myapp --parallel=50%
```
Note, you can also change the default in `nx.json`, like this: Note, you can also change the default in `nx.json`, like this:
{% tabs %} {% tabs %}

View File

@ -1,6 +1,7 @@
import * as yargs from 'yargs'; import * as yargs from 'yargs';
import { import {
readParallelFromArgsAndEnv,
withAffectedOptions, withAffectedOptions,
withOutputStyleOption, withOutputStyleOption,
withRunManyOptions, withRunManyOptions,
@ -130,3 +131,47 @@ describe('shared-options', () => {
); );
}); });
}); });
describe('readParallelFromArgsAndEnv', () => {
it('default parallel should be 3', () => {
const result = readParallelFromArgsAndEnv({ parallel: 'true' });
expect(result).toEqual(3);
});
it('use maxParallel', () => {
const result = readParallelFromArgsAndEnv({
parallel: '',
maxParallel: '4',
});
expect(result).toEqual(4);
});
it('use max-parallel', () => {
const result = readParallelFromArgsAndEnv({
parallel: '',
'max-parallel': '5',
});
expect(result).toEqual(5);
});
it('should read parallel 6', () => {
const result = readParallelFromArgsAndEnv({
parallel: '6',
});
expect(result).toEqual(6);
});
it('0% parallel should be 1', () => {
const result = readParallelFromArgsAndEnv({
parallel: '0%',
});
expect(result).toEqual(1);
});
it('100% parallel should not be less than 1', () => {
const result = readParallelFromArgsAndEnv({
parallel: '100%',
});
expect(result).toBeGreaterThanOrEqual(1);
});
});

View File

@ -2,6 +2,7 @@ import { readNxJson } from '../../config/nx-json';
import { shouldUseTui } from '../../tasks-runner/is-tui-enabled'; import { shouldUseTui } from '../../tasks-runner/is-tui-enabled';
import { NxArgs } from '../../utils/command-line-utils'; import { NxArgs } from '../../utils/command-line-utils';
import { Argv, coerce, ParserConfigurationOptions } from 'yargs'; import { Argv, coerce, ParserConfigurationOptions } from 'yargs';
import { availableParallelism, cpus } from 'node:os';
interface ExcludeOptions { interface ExcludeOptions {
exclude: string[]; exclude: string[];
@ -380,17 +381,17 @@ export function readParallelFromArgsAndEnv(args: { [k: string]: any }) {
args['parallel'] === 'true' || args['parallel'] === 'true' ||
args['parallel'] === true || args['parallel'] === true ||
args['parallel'] === '' || args['parallel'] === '' ||
// dont require passing --parallel if NX_PARALLEL is set, but allow overriding it // don't require passing --parallel if NX_PARALLEL is set, but allow overriding it
(process.env.NX_PARALLEL && args['parallel'] === undefined) (process.env.NX_PARALLEL && args['parallel'] === undefined)
) { ) {
return Number( return concurrency(
args['maxParallel'] || args['maxParallel'] ||
args['max-parallel'] || args['max-parallel'] ||
process.env.NX_PARALLEL || process.env.NX_PARALLEL ||
3 '3'
); );
} else if (args['parallel'] !== undefined) { } else if (args['parallel'] !== undefined) {
return Number(args['parallel']); return concurrency(args['parallel']);
} }
} }
@ -407,3 +408,13 @@ const coerceTuiAutoExit = (value: string) => {
} }
throw new Error(`Invalid value for --tui-auto-exit: ${value}`); throw new Error(`Invalid value for --tui-auto-exit: ${value}`);
}; };
function concurrency(val: string | number) {
let parallel = typeof val === 'number' ? val : parseInt(val);
if (typeof val === 'string' && val.at(-1) === '%') {
const maxCores = availableParallelism?.() ?? cpus().length;
parallel = (maxCores * parallel) / 100;
}
return Math.max(1, Math.floor(parallel));
}