Skip to content

Commit 35807cf

Browse files
[CI] Speed up GitLab Windows build with parallel C++ compilation (#8925)
## Summary of changes Enable MSVC multiprocessor compilation for the GitLab Windows build, capped at the runner's 16 logical processors. Increase the container memory limit from 10 GB to 20 GB and log runner and peak container memory. ## Reason for change The Windows GitLab build took around 40 minutes. Native compilation accounted for 24:52 of the 31:45 NUKE execution. ## Implementation details Set `ENABLE_MULTIPROCESSOR_COMPILATION=true` and `CL_MPCount=16`. The runner has 16 logical processors and approximately 31 GB of RAM. Peak container usage with MP16 was 9.105 GiB. ## Test coverage | Configuration | NUKE | Native compilation | End-to-end | Peak container memory | | --- | ---: | ---: | ---: | ---: | | Baseline, MP disabled / 10 GB | 31:45 | 24:52 | ~40 min | Not measured | | MP2 / 10 GB | 22:27 | 14:40 | ~29–31 min | Not measured | | MP3 / 10 GB | Not measured | Not measured | ~24–28 min | Not measured | | MP4 / 16 GB | 15:00–15:54 | Not measured | ~17–23 min | Not measured | | MP8 / 16 GB | 13:50 | 6:01 | 23:27 | Not measured | | MP8 / 20 GB | 13:11 | 5:44 | 21:31 | 8.686 GiB | | MP16 / 20 GB | 11:37 | 4:37 | 19:54 | 9.105 GiB | | Configuration | Tracer | Loader | Profiler | | --- | ---: | ---: | ---: | | Baseline | 8:38 | 2:46 | 13:28 | | MP2 / 10 GB | 5:15 | 1:40 | 7:45 | | MP8 / 16 GB | 2:21 | 0:42 | 2:58 | | MP8 / 20 GB | 2:13 | 0:41 | 2:50 | | MP16 / 20 GB | 1:50 | 0:33 | 2:14 | MP16 reduced NUKE time by approximately 63% and cold end-to-end time by approximately 50% compared with `master`. All runs completed without OOM or compiler failures. End-to-end variance was mostly caused by the 7–9 minute Docker image pull.
1 parent 821b067 commit 35807cf

1 file changed

Lines changed: 78 additions & 3 deletions

File tree

.gitlab-ci.yml

Lines changed: 78 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,10 +108,72 @@ build:
108108
exit 1
109109
}
110110
- |
111-
docker run --rm -m 10240M `
111+
try {
112+
$computerSystem = Get-CimInstance Win32_ComputerSystem
113+
$operatingSystem = Get-CimInstance Win32_OperatingSystem
114+
Write-Output ("Runner memory: {0:N1} GB total, {1:N1} GB free" -f ($computerSystem.TotalPhysicalMemory / 1GB), ($operatingSystem.FreePhysicalMemory * 1KB / 1GB))
115+
Write-Output "Runner logical processors: $($computerSystem.NumberOfLogicalProcessors)"
116+
} catch {
117+
Write-Warning "Unable to retrieve runner information: $_"
118+
}
119+
120+
$containerName = "dd-trace-build-$env:CI_JOB_ID"
121+
$containerMemoryLimit = 20GB
122+
$dockerPath = (Get-Command docker).Source
123+
$statsJob = Start-Job -ArgumentList $containerName, $containerMemoryLimit, $dockerPath -ScriptBlock {
124+
param($name, $memoryLimit, $docker)
125+
126+
function ConvertTo-Bytes([string] $value) {
127+
if ($value -notmatch '^\s*([0-9]+(?:\.[0-9]+)?)\s*([KMGT]?i?B)\s*$') {
128+
return $null
129+
}
130+
131+
$factors = @{
132+
B = 1
133+
KB = 1KB
134+
KiB = 1KB
135+
MB = 1MB
136+
MiB = 1MB
137+
GB = 1GB
138+
GiB = 1GB
139+
TB = 1TB
140+
TiB = 1TB
141+
}
142+
143+
return [double]$Matches[1] * $factors[$Matches[2]]
144+
}
145+
146+
$containerSeen = $false
147+
$peakBytes = 0.0
148+
$peakUsage = "unknown"
149+
150+
while ($true) {
151+
$stats = & $docker stats $name --no-stream --format "{{.MemUsage}}" 2>$null
152+
if ($LASTEXITCODE -eq 0 -and $stats) {
153+
$containerSeen = $true
154+
$usage = ($stats -split '/', 2)[0].Trim()
155+
$usageBytes = ConvertTo-Bytes $usage
156+
if ($null -ne $usageBytes -and $usageBytes -gt $peakBytes) {
157+
$peakBytes = $usageBytes
158+
$peakUsage = $usage
159+
}
160+
} elseif ($containerSeen) {
161+
break
162+
}
163+
164+
Start-Sleep -Seconds 5
165+
}
166+
167+
$peakPercent = 100 * $peakBytes / $memoryLimit
168+
Write-Output ("Peak container memory: {0} ({1:N1}% of limit)" -f $peakUsage, $peakPercent)
169+
}
170+
171+
# Enable MSVC /MP, capped at the runner's logical processor count.
172+
docker run --name $containerName --rm -m 20480M `
112173
-v "$(Get-Location):c:\mnt" `
113174
-e CI_JOB_ID=${CI_JOB_ID} `
114-
-e ENABLE_MULTIPROCESSOR_COMPILATION=false `
175+
-e ENABLE_MULTIPROCESSOR_COMPILATION=true `
176+
-e CL_MPCount=16 `
115177
-e WINDOWS_BUILDER=true `
116178
-e AWS_NETWORKING=true `
117179
-e SIGN_WINDOWS=true `
@@ -121,6 +183,19 @@ build:
121183
-e CI_JOB_NAME_SLUG `
122184
$env:WINDOWS_BUILD_IMAGE `
123185
Info Clean BuildTracerHome BuildProfilerHome BuildNativeLoader BuildDdDotnet PublishFleetInstaller PackageTracerHome ZipSymbols SignDlls SignMsi DownloadWinSsiTelemetryForwarder
186+
$buildExitCode = $LASTEXITCODE
187+
188+
Wait-Job $statsJob -Timeout 15 | Out-Null
189+
if ($statsJob.State -eq 'Running') {
190+
Stop-Job $statsJob
191+
}
192+
193+
Receive-Job $statsJob
194+
Remove-Job $statsJob -Force
195+
196+
if ($buildExitCode -ne 0) {
197+
throw "Docker build container exited with code $buildExitCode"
198+
}
124199
- mkdir artifacts-out
125200
- xcopy /e/s build-out\${CI_JOB_ID}\*.* artifacts-out
126201
- remove-item -recurse -force build-out\${CI_JOB_ID}
@@ -377,4 +452,4 @@ update_central_configurations_version_range_v2:
377452
variables:
378453
LOCAL_CONFIG_PATH: $SUPPORTED_CONFIG_PATH
379454
LANGUAGE_NAME: "dotnet"
380-
SEND_ALIASES: true
455+
SEND_ALIASES: true

0 commit comments

Comments
 (0)