--parallel workers versus --grep filtering under limited CI memory
0 reputation · 23 Jul 2022, 06:29 UTC
0 reputation · 23 Jul 2022, 06:29 UTC
The goal is to keep CI test runs fast while staying within a fixed CPU and memory quota for a Mocha suite. Two documented approaches are available: using --parallel to distribute tests across worker processes, and using --grep to select a subset of tests by name pattern.
--parallel can reduce wall-clock time on multi-core runners but raises per-worker memory pressure and does not propagate global before/after hooks across workers. --grep reduces the number of tests executed, but its interaction with --parallel is version-dependent and the combined behavior is not clearly deterministic across platforms. Output ordering with both flags is reported as potentially interleaved, which complicates debugging.
For a design decision under limited CI resources, is the test selection performed by --grep guaranteed to be applied before work is distributed to --parallel workers in Mocha 10.x? Does the combination produce deterministic test ordering and reporting across platforms? How does the lack of global hook propagation affect setups that rely on shared initialization when both flags are used together?
34775 reputation · 23 Jul 2022, 16:50 UTC
No, --grep filtering is not applied before work distribution. In Mocha 10.x, each worker process loads the full test suite independently and applies the grep pattern locally. The combination does not produce deterministic test ordering or reporting across platforms. Global hooks (root-level before, after, beforeEach, afterEach) execute once per worker, multiplying initialization cost and memory usage by the worker count.
worker_threads. Each worker receives the complete test file list and instantiates its own Mocha runner. The grep pattern is passed as a configuration option to each worker's Mocha instance (lib/cli/run-helpers.js, lib/parallel-buffer.js). No central pre-filtering occurs.before will open N connections (where N = worker count).--grep reduces executed tests but not loaded modules. Memory scales roughly linearly with --parallel count.| Approach | Wall-clock Time | Peak Memory | Hook Cost | Debuggability |
|---|---|---|---|---|
--parallel 4 alone | Lowest (ideal scaling) | 4× baseline | 4× global hooks | Poor (interleaved output) |
--grep "pattern" alone | Proportional to matched tests | 1× baseline | 1× global hooks | Good (serial output) |
--parallel 4 --grep "pattern" | Lowest for matched subset | 4× baseline | 4× global hooks | Poor (interleaved + non-deterministic) |
--parallel. Use --grep to shard the suite across multiple CI jobs instead (e.g., --grep "@smoke", --grep "@integration"). Each job runs serially with one global hook execution.--parallel with a worker count tuned to your memory quota (e.g., --parallel 2 on a 2-core/4GB runner). Add --reporter=json or a custom reporter that prefixes output with worker ID to make interleaved logs readable.before) being visible across workers. Each worker has its own process memory.# 1. Confirm Mocha version
mocha --version
# 2. Observe hook execution count
mocha --parallel 3 --grep "smoke" --reporter=spec 2>&1 | grep -c "global before"
# Expect: 3 lines (once per worker)
# 3. Check ordering determinism
for i in {1..5}; do mocha --parallel 2 --grep "smoke" --reporter=spec 2>&1 | grep -E "^ [0-9]+ passing" | head -1; done
# Expect: varying order across runs
What is the peak RSS memory of a single worker running your full suite (without --parallel)? Run /usr/bin/time -v mocha 2>&1 | grep "Maximum resident" on Linux or use memory_profiler in Node. This determines the maximum safe --parallel value for your CI memory quota.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.