feat: introduce SNYK_REQUEST_CONCURRENCY for dependency request parallelism#6756
feat: introduce SNYK_REQUEST_CONCURRENCY for dependency request parallelism#6756
Conversation
…lelism Add a tunable concurrency knob for in-flight dependency-test/dependency-monitor HTTP requests, default 10 (raised from the prior hard-coded 5), clamped to [1, 50]. Override via the SNYK_REQUEST_CONCURRENCY environment variable. Apply the new helper at the existing pMap call site in sendAndParseResults (run-test.ts). The default bump is effectively a no-op for non-container test workloads (single-project tests produce one payload; --all-projects rarely produces more than the prior 5-payload ceiling), but materially improves wall-clock for container tests that produce one ScanResult per directory containing dependencies. A follow-up PR will adopt the same helper in the container monitor path, which is currently fully sequential.
✅ Snyk checks have passed. No issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
|
Benchmark —
|
| Configuration | Mean wall-clock | vs baseline |
|---|---|---|
baseline (c=5) |
68.04 s ± 1.72 s | 1.00× |
PR A default (c=10) |
40.96 s ± 0.15 s | 1.66× faster (−40%) |
PR A override (c=20) |
25.13 s ± 0.48 s | 2.71× faster (−63%) |
Each config: 3 runs after 1 warmup; image pre-pulled. Min/max within ±2% of mean across all configs — variance is tight.
Standard deviation drops with higher concurrency (1.72s → 0.15s → 0.48s) because the wait-time component shrinks and the scan becomes more CPU-bound on the (much steadier) JAR-extraction work in snyk-docker-plugin.
PR Reviewer Guide 🔍
|
What does this PR do?
Adds a tunable concurrency knob for in-flight dependency-test / dependency-monitor HTTP requests, and bumps the default from 5 to 10.
getRequestConcurrency()insrc/lib/snyk-test/common.ts— readsSNYK_REQUEST_CONCURRENCY, defaults to 10, clamps to[1, 50].MAX_CONCURRENCY = 5constant at the existingpMapcall site insendAndParseResults(src/lib/snyk-test/run-test.ts).A follow-up PR (#6757) adopts the same helper in
src/lib/ecosystems/monitor.ts:monitorDependencies, which is currently fully sequential.Why?
snyk container testproduces oneScanResultper directory of dependencies in the image (lib/analyzer/applications/java.ts:groupJarFingerprintsByPathinsnyk-docker-plugin). For Java-heavy images this can be hundreds of ScanResults, each becoming a separatePOST /test-dependenciesrequest. With the prior concurrency cap of 5, the request fan-out is the dominant wall-clock cost.Benchmark —
quay.io/wildfly/wildfly:34.0.1.Final-jdk21(512 ScanResults)hyperfine --warmup 1 --runs 3against the same locally-built PR binary, varying onlySNYK_REQUEST_CONCURRENCYto isolate the API concurrency change from any other build/runtime differences. Thec=5row reproduces the prior hard-coded value, so it's an apples-to-apples baseline.c=5)c=10)c=20)Min/max within ±2% of mean across all configs — variance is tight. Standard deviation drops with higher concurrency (1.72s → 0.15s → 0.48s) because the wait-time component shrinks and the scan becomes more CPU-bound on the (much steadier) JAR-extraction work in
snyk-docker-plugin.For non-container test workloads the default bump is essentially a no-op:
--all-projectsrarely produces more than the prior 5-payload ceiling.Where should the reviewer start?
src/lib/snyk-test/common.ts— new helper.src/lib/snyk-test/run-test.ts— single call-site swap.test/jest/unit/lib/snyk-test/common.spec.ts— 9 new unit tests for the helper covering default, override, clamping, and invalid-input cases.How should this be manually tested?
npx jest --selectProjects coreCli --testPathPattern 'test/jest/unit/lib/snyk-test/common.spec'Risk assessment
Low. The change is scoped to a single constant + a small env-var helper. Default behavior change (5 → 10) only affects test invocations that produce more than 5 payloads, which today means container tests and large
--all-projectsruns. The override is bounded to[1, 50]to prevent footguns.Background
Supersedes #6747 (which targeted the wrong code path —
src/lib/ecosystems/test.ts:testDependenciesis unreachable fromsnyk container test;getEcosystemForTestreturns null for docker, so container test goes throughrunTest/pMapinstead).