Files
local-ci-cd-system/docs/OPTIMIZATION.md
T
Simone 6ba8cca70a docs: fix stale references across all documentation
- ARCHITECTURE.md: fix WinRM subnet (192.168.1179), VM box shows VS 2026/Python 3.13/unzip+python build instead of .NET SDK 8/git clone/dotnet build
- BEST-PRACTICES.md: fix VMnet11/192.168.11  VMnet8 NAT/192.168.79
- CI-FLOW.md: Step 3 workflow YAML updated to actual Invoke-CIJob.ps1 params (Submodules, BuildCommand, GuestArtifactSource); note that -VMIPAddress is auto-detected
- OPTIMIZATION.md: BaseClean tier updated to VS BuildTools 2026, .NET SDK 10.0.203, Python 3.13.3
- gitea/workflow-example.yml: remove BUILD_VM_IP (auto-detected), replace -VMIPAddress/-Configuration with -Submodules/-BuildCommand/-GuestArtifactSource
2026-05-08 23:36:57 +02:00

198 lines
6.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Optimization Strategies
## 1. Linked Clone Disk Layout
**Goal:** Minimize clone creation time and I/O contention between concurrent VMs.
### Recommended NVMe Partition Layout
```
NVMe SSD (e.g. 2TB)
├── C:\ — Windows host OS, VMware Workstation installation
├── F:\CI\
│ ├── Templates\ — Template VM VMX + base VMDK (parent snapshot)
│ ├── BuildVMs\ — Ephemeral linked clone VMs (delta VMDKs)
│ ├── Artifacts\ — Collected build artifacts (per job)
│ ├── Cache\ — NuGet / npm cache (see §4)
│ └── RunnerWork\ — act_runner workspace (checkout, step scripts)
```
**Why separate directories matter:**
- Template VMDK reads (CoW base) and clone delta writes happen simultaneously
- Keeping them on the same fast NVMe avoids I/O stalls; a separate spinning disk for
the clone directory would bottleneck clone creation
- Artifacts and cache dirs have sequential I/O patterns; they can share space
---
## 2. Snapshot Strategy
### Tiered Snapshot Model
```
Tier 0: Base OS Install (Windows only, no tools)
└── Snapshot: "OSBase" — rarely updated (yearly or on major Windows updates)
Tier 1: Build Toolchain
└── Snapshot: "BaseClean" ← CLONE SOURCE (weekly refresh)
Includes: VS Build Tools 2026, .NET SDK 10.0.203, Python 3.13.3, Git, WinRM config
Requirement: ALL linked clones must reference this exact snapshot
```
### Refresh Schedule
| Snapshot | Refresh Frequency | Trigger |
| ----------- | ----------------- | ------------------------------------------ |
| `OSBase` | Quarterly | Windows cumulative update |
| `BaseClean` | Weekly/Monthly | .NET SDK patch, security update, VS update |
> **Note:** Windows Server 2025 KMS lease = 180 giorni. Prima della scadenza:
> boot template su VMnet8 (NAT) → `slmgr /ato` → spegni → nuovo snapshot `BaseClean`.
---
## 3. Parallel Build Capacity
### RAM Budget (i9-10900X · 64 GB)
| Component | RAM Usage |
| ------------------------------------- | --------- |
| Windows host OS | ~4 GB |
| VMware Workstation | ~0.5 GB |
| Gitea server | ~0.51 GB |
| act_runner service | ~100 MB |
| Each build VM (idle) | ~23 GB |
| Each build VM (active MSBuild/Python) | ~68 GB |
| **Headroom target (20%)** | ~13 GB |
```
Available for VMs: 64 - 4 - 0.5 - 1 - 0.1 - 13 = ~45 GB
Max VMs at peak: 45 / 8 = ~5.6 → safe limit = 4
```
**Recommendation:** `capacity: 4` in `config.yaml`.
### CPU Budget (i9-10900X: 10 cores / 20 threads)
- Template VM: 4 vCPU configurati
- Con 4 VM parallele: 4 × 4 = 16 thread, lascia 4 per host OS / Gitea / runner
- `build_plugin.py` usa `get_optimal_thread_count()` che rileva i core della VM e divide per il numero di build parallele (fix TRK0002)
### VM Configuration (template VMX)
```ini
numvcpus = "4"
cpuid.coresPerSocket = "2"
memsize = "6144" # 6 GB RAM per VM
scsi0.virtualDev = "pvscsi"
ethernet0.virtualDev = "vmxnet3"
```
---
## 4. NuGet / Package Cache on Host
**Problem:** Each build VM does a fresh `dotnet restore`, re-downloading NuGet packages every time.
**Solution:** Map a host-side NuGet cache directory as a shared folder into each VM.
### Setup (host side)
```
F:\CI\Cache\NuGet\ ← shared folder on host
```
### VMware Shared Folder Configuration (in template VMX)
Add to `WinBuild.vmx` before taking the `BaseClean` snapshot:
```ini
sharedFolder0.present = "TRUE"
sharedFolder0.enabled = "TRUE"
sharedFolder0.readAccess = "TRUE"
sharedFolder0.writeAccess = "TRUE"
sharedFolder0.hostPath = "F:\\CI\\Cache\\NuGet"
sharedFolder0.guestName = "nuget-cache"
sharedFolder.maxNum = "1"
```
Inside the VM, the shared folder appears as `\\vmware-host\Shared Folders\nuget-cache`.
### NuGet Cache Redirect (in `Invoke-RemoteBuild.ps1`)
Add to the remote build ScriptBlock:
```powershell
$env:NUGET_PACKAGES = '\\vmware-host\Shared Folders\nuget-cache'
dotnet restore --packages $env:NUGET_PACKAGES
```
**Result:** First build per package downloads once; subsequent builds read from the host cache.
Cache is shared across all concurrent VMs (NuGet packages are safe for concurrent reads).
---
## 5. Clone Pre-Warming
For latency-sensitive pipelines, keep N pre-warmed clones ready in "booted and idle" state.
**Tradeoff:** Saves ~4590 seconds of startup per job, but clones remain running (consuming RAM) until used.
**Implementation sketch:**
```powershell
# Pre-warmer job (separate scheduled task on host)
# Runs between CI jobs to maintain a pool of warm VMs
$poolSize = 2 # Keep 2 VMs warm at all times
# Check current running clones
$runningClones = Get-ChildItem F:\CI\WarmPool\ -Filter *.vmx
if ($runningClones.Count -lt $poolSize) {
# Create and start new clone in warm pool
$vmx = .\New-BuildVM.ps1 -TemplatePath $template -CloneBaseDir F:\CI\WarmPool -JobId "warm-$(Get-Random)"
vmrun -T ws start $vmx nogui
}
```
> **Note:** Pre-warming is an advanced optimization. Start without it and add
> only if CI overhead (startup time) is a demonstrated bottleneck.
---
## 6. Artifact Storage Management
Build artifacts accumulate quickly. Automate cleanup:
```powershell
# Scheduled task: run daily
# Remove artifact dirs older than 30 days
Get-ChildItem 'F:\CI\Artifacts' -Directory |
Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-30) } |
Remove-Item -Recurse -Force
# Remove orphaned clone directories (VMs that were not properly deleted)
Get-ChildItem 'F:\CI\BuildVMs' -Directory |
Where-Object { $_.LastWriteTime -lt (Get-Date).AddHours(-4) } |
ForEach-Object {
$vmx = Get-ChildItem $_.FullName -Filter *.vmx | Select-Object -First 1
if ($vmx) {
vmrun -T ws stop $vmx.FullName hard 2>$null
}
Remove-Item $_.FullName -Recurse -Force
}
```
---
## 7. NUMA & CPU Affinity (Advanced)
The i9-10900X is a single NUMA node CPU (no NUMA effects). CPU pinning is not needed.
However, you can set CPU affinity per VM group to reduce vCPU migration overhead:
```powershell
# Optional: pin act_runner process to cores 0-3 (leave build VMs on 4-19)
$runnerPid = (Get-Process act_runner).Id
Start-Process -FilePath 'cmd' -ArgumentList "/c start /affinity 0xF /b /wait powershell" -NoNewWindow
```
For most workloads, Windows scheduler handles this well — skip affinity unless profiling shows issues.