Skip to content

Commit

Permalink
enhance(gateway-cli): respect available memory while forking processes
Browse files Browse the repository at this point in the history
  • Loading branch information
ardatan committed Nov 1, 2024
1 parent 2eee423 commit 33eb2e5
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 5 deletions.
5 changes: 5 additions & 0 deletions .changeset/serious-buses-learn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@graphql-hive/gateway': patch
---

Respect available memory on forking the processes not just CPU
11 changes: 6 additions & 5 deletions packages/gateway/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { DefaultLogger } from '@graphql-mesh/utils';
import parseDuration from 'parse-duration';
import { addCommands } from './commands/index';
import { createDefaultConfigPaths } from './config';
import { getMaxConcurrency } from './getMaxConcurrency';
import type { ServerConfig } from './server';

export type GatewayCLIConfig = (
Expand Down Expand Up @@ -178,9 +179,9 @@ export type AddCommand = (ctx: CLIContext, cli: CLI) => void;

// we dont use `Option.default()` in the command definitions because we want the CLI options to
// override the config file (with option defaults, config file will always be overwritten)
const maxAvailableFork = Math.max(availableParallelism() - 1, 1);
const maxFork = getMaxConcurrency();
export const defaultOptions = {
fork: process.env['NODE_ENV'] === 'production' ? maxAvailableFork : 1,
fork: process.env['NODE_ENV'] === 'production' ? maxFork : 1,
host:
platform().toLowerCase() === 'win32' ||
// is WSL?
Expand All @@ -200,17 +201,17 @@ let cli = new Command()
.addOption(
new Option(
'--fork <count>',
`count of workers to spawn. uses "${maxAvailableFork}" (available parallelism) workers when NODE_ENV is "production", otherwise "1" (the main) worker (default: ${JSON.stringify(defaultOptions.fork)}`,
`count of workers to spawn. uses "${maxFork}" (available parallelism) workers when NODE_ENV is "production", otherwise "1" (the main) worker (default: ${JSON.stringify(defaultOptions.fork)}`,
)
.env('FORK')
.argParser((v) => {
const count = parseInt(v);
if (isNaN(count)) {
throw new InvalidArgumentError('not a number.');
}
if (count > maxAvailableFork) {
if (count > maxFork) {
throw new InvalidArgumentError(
`exceedes number of available parallelism "${maxAvailableFork}".`,
`exceedes number of available parallelism "${maxFork}".`,
);
}
return count;
Expand Down
21 changes: 21 additions & 0 deletions packages/gateway/src/getMaxConcurrency.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { availableParallelism, freemem } from 'node:os';

function getFreeMemInGb() {
return freemem() / 1024 ** 3;
}

function getMaxConcurrencyPerMem() {
return parseInt(String(getFreeMemInGb()));
}

function getMaxConcurrencyPerCpu() {
return availableParallelism();
}

export function getMaxConcurrency() {
const result = Math.min(getMaxConcurrencyPerMem(), getMaxConcurrencyPerCpu());
if (result < 1) {
return 1;
}
return result;
}

0 comments on commit 33eb2e5

Please sign in to comment.