Skip to content

Commit 302f9bc

Browse files
iliapolomrgrain
andauthored
feat(cli-integ): calculate maxWorkers based on machine spec (#423)
In order to be able to run on various machine types, calculate the max number of workers based on the total memory and CPU cores available in the machine. With this calculation we get: - CLI Repo (64GB & 16 Cores) = `Math.min(16 * 15, (64000 - 2000) / (0.7 * 500)) = Math.min(240, 177) = 177` - CodeBuild Canary (16GB & 8 Cores) = `Math.min(8 * 15, (16000 - 2000) / (0.7 * 500)) = Math.min(120, 40) = 40` - CodeBuild Release & Main (72GB & 32 Cores) = `Math.min(32 * 15, (72000 - 2000) / (0.7 * 500)) = Math.min(480, 200) = 200` ### Memory Data Here is some memory usage sampling i've [added](#422) to confirm our memory consumption stats: ```console 2025-04-29T09:50:51.525Z | [pre-callback] [test] Memory RSS: 152 MB 2025-04-29T09:50:51.200Z | [pre-callback] [test] Memory RSS: 150 MB 2025-04-29T09:50:50.836Z | [pre-callback] [test] Memory RSS: 150 MB 2025-04-29T09:54:08.055Z | [post-callback] [test] Memory RSS: 122 MB 2025-04-29T09:54:08.797Z | [post-callback] [test] Memory RSS: 114 MB 2025-04-29T09:54:12.054Z | [post-callback] [test] Memory RSS: 113 MB 2025-04-29T09:53:06.601Z | [pre-tree] [app.js] Memory RSS: 49 MB 2025-04-29T09:53:10.468Z | [pre-tree] [app.js] Memory RSS: 49 MB 2025-04-29T09:54:04.682Z | [pre-tree] [app.js] Memory RSS: 49 MB 2025-04-29T09:53:07.836Z | [post-tree] [app.js] Memory RSS: 105 MB 2025-04-29T09:54:05.071Z | [post-tree] [app.js] Memory RSS: 106 MB 2025-04-29T09:53:11.895Z | [post-tree] [app.js] Memory RSS: 105 MB 2025-04-29T09:53:08.864Z | [post-synth] [app.js] Memory RSS: 139 MB 2025-04-29T09:53:13.215Z | [post-synth] [app.js] Memory RSS: 139 MB 2025-04-29T09:54:05.367Z | [post-synth] [app.js] Memory RSS: 138 MB 2025-04-29T09:53:09.219Z | [post-synth] [cli] Memory RSS: 200 MB 2025-04-29T09:53:13.359Z | [post-synth] [cli] Memory RSS: 203 MB 2025-04-29T09:54:05.437Z | [post-synth] [cli] Memory RSS: 202 MB 2025-04-29T09:53:10.358Z | [pre-synth] [cli] Memory RSS: 201 MB 2025-04-29T09:54:04.627Z | [pre-synth] [cli] Memory RSS: 183 MB ``` From here we see that: - Memory consumed by jest process: ~150MB - Memory consumed by CDK App subprocess: ~140MB - Memory consumed by CLI subprocess: ~200MB ## Notes - These numbers suggest a total of about 500MB per worker...multiple that by 50 and you get 25GB - way above the 16GB we were running with. Stands to reason that a simple 500 X 50 multiplication doesn't accurately describe the total max memory consumption of the suite. - Its surprising that the memory consumed by jest after the callback finishes is less than before the callback starts. --- By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license --------- Co-authored-by: Momo Kornher <[email protected]>
1 parent 4068210 commit 302f9bc

File tree

3 files changed

+36
-3
lines changed

3 files changed

+36
-3
lines changed

.github/workflows/integ.yml

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.projenrc.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1647,7 +1647,6 @@ new CdkCliIntegTestsWorkflow(repo, {
16471647
testEnvironment: TEST_ENVIRONMENT,
16481648
buildRunsOn: POWERFUL_RUNNER,
16491649
testRunsOn: POWERFUL_RUNNER,
1650-
maxWorkers: '80',
16511650

16521651
localPackages: [
16531652
cloudAssemblySchema.name,

packages/@aws-cdk-testing/cli-integ/resources/integ.jest.config.js

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
const path = require('path');
2+
const os = require('os');
23

34
const rootDir = path.resolve(__dirname, '..', 'tests', process.env.TEST_SUITE_NAME);
45

@@ -19,9 +20,42 @@ module.exports = {
1920
// for the lock. Which is almost never what we actually care about. Set it high.
2021
testTimeout: 2 * 60 * 60_000,
2122

22-
maxWorkers: 50,
23+
maxWorkers: maxWorkers(),
2324
reporters: [
2425
"default",
2526
["jest-junit", { suiteName: "jest tests", outputDirectory: "coverage" }]
2627
]
2728
};
29+
30+
/**
31+
* Based on the machine spec, calcluate the maximum number of jest workers we can start in parallel.
32+
*/
33+
function maxWorkers() {
34+
35+
const totalMachineMemoryMB = os.totalmem() / 1024 / 1024;
36+
const totalMachineCores = os.cpus().length;
37+
38+
// empirically observed. this includes:
39+
// - 150 jest test process
40+
// - 140 app synthesis subprocess
41+
// - 200 cli subprocess
42+
const maxWorkerMemoryMB = 500;
43+
44+
// we take a factor of the total because not all 3 subprocess
45+
// consume their max theoretical memory at the same time.
46+
// 0.7 is an eyeballed factor that seems to work well.
47+
const averageWorkerMemoryMB = 0.7 * maxWorkerMemoryMB;
48+
49+
// leave some memory for the OS and other external processes
50+
const reservedMemoryMB = 2000;
51+
52+
// our processes don't take up much CPU so we allow for a large factor.
53+
const cpuScaleFactor = 15;
54+
55+
const byMemory = Math.floor((totalMachineMemoryMB - reservedMemoryMB) / (averageWorkerMemoryMB));
56+
const byCpu = cpuScaleFactor * totalMachineCores;
57+
58+
const maxWorkers = Math.min(byMemory, byCpu);
59+
console.log(`[integ.jest.config] calculated maxWorkers: ${maxWorkers}`)
60+
return maxWorkers;
61+
}

0 commit comments

Comments
 (0)