CI Performance - netcup Runner vs. WarpBuild
Für eine bessere Entscheidungsfindung müssen Messungen auf dem netcup RS 8000 G12 (Windows) gegen die bestehenden WarpBuild Runner gemacht werden.
Roh-Metriken
| Messung | netcup | WarpBuild | Github/Azure |
|---|---|---|---|
7z b -mmt1 | 4346 MIPS | 6891 MIPS | 5104 MIPS |
| (Compressing) | 2874 MIPS | 5851 MIPS | 3990 |
| Taktung | 3.1 GHz | 3.69 GHz | 2.9 GHz |
| BDD-Assembly (16k Tests) | 42m | 24m10s | 1h3m |
| Checkout cmi-metatool (full) | 60s | ~60s | ~60s |
Performanceoptimierung über Warp
In diesen Tests wurde ein enormes Bottleneck entdeckt.
Die Schultests blockieren den kompletten Arbeitsspeicher, auch wenn Sie nur 25% der Tests ausmachen.
Nach dem Sharding auf GitHub (Schule / Rest, zwei Runner) entstehen folgende Metriken:
| Konfiguration | Laufzeit |
|---|---|
| 1x 8x, ungeshardet (alt) | 24m10s |
| 2x 4x, Schule-Split (neu) | 16m06s |
| 2x 8x, Schule-Split | 13m20s |
Die 2x 4x Variante ist etwa gleich teuer wie heute, dabei alleridngs 33% schneller.
Aus diesem Grund wurde mit diesem PR die Umstellung auf 2x4x gesetzt,
wodurch die effektive Wartezeit um 10 Minuten reduziert werden konnte.
Grundlegene Probleme
Während im Linux Bereich auf Netcup Alles mehr als genügend ist,
kristallisiert sich auf Windows (und damit für CMInformatik/cmi-metatool) ein Problem heraus.
Die Root-Server von netcup sind leider nicht metal sondern quasi eine VPS mit dedizierten Kernen.
Daraus ergibt sich zum einen der leider immer noch enorme Performance Overhead durch die CPU virtualisierung,
zum Andern aber das Hauptproblem, mit dem wir vor Allem in den BDD Tests kämpfen müssen:
Memory-Bandbreite
Sharding auf 3 Prozesse hob die CPU-Last von 27% auf 90%, der Durchsatz fiel aber um ein Drittel (39 min -> 58m24s).
Parallelisierung hilft dort nicht, sie schadet.
Während die Infrastruktur immer noch weit besser dasteht, als ihr Pendant auf Github (also Azure),
läuft auf den Warp Instanzen Gaming Hardware, die gerade in diese Bandbreiten gebundenen Szenarien ihre konkurrenz zerstört.
Kein git filter
filter: blob:none würde den checkout von 900MiB auf knapp 380MiB reduzieren.
Da wir hier allerdings Nerdbank für die Versionierung verwenden,
kann das nicht gverwendet werden:
Unable to get version from commit
Dies erklärt auch den revert in cmi-metatool#9723 aus 2024.
Azure Disk der Forgejo-Instanz
Gemäss cmi-prod-infrastructure bekam die Forgejo Instanz eine PremiumV2_LRS mit 3000 IOPS (250 MB/s)
und cachingMode: None für bessere Performance.
Im realen Gebrauch (also random IOPS) zeichnet sich ein düsteres Bild ab
- Artifact-Upload (1.9 GB): 55s = 34.5 MB/s,
also gerade einmal ein Siebtel der angegebenen Bandbreite.
Uploads erfolgen in 8MiB grossen Chunks mit ca. 200ms Overhead. - 5 parallele Downloads: je ~30 MB/s.
Um das zu mitigieren, müsste zumindest für die Artefakte ein S3 mittels silo auf einem der Runner gehostet werden.
Kosten fuer echte dedizierte Hardware
Ein Hetzner AX102-1 für 259€ /Mo (+ 129€ einmalig) liefert:
- CPU: AMD Ryzen 9 7950X3D, 16C/32T,
- RAM: 128 GB DDR5
- Disk: 2x 1.92 TB NVMe.
| Anzahl | EUR/Monat | Setup einmalig |
|---|---|---|
| 2 Maschinen | 518.00 | 258 |
| 3 Maschinen | 777.00 | 387 |
| 4 Maschinen | 1036.00 | 516 |
Drei Maschinen sind die Empfehlung: Peak-Parallelitaet einer vollen Pipeline sind 8 Windows-Jobs, der Gesamtverbrauch liegt aber nur bei ~122 Runner-Stunden im Monat. Die 10-Gbit-Option (43 EUR) ist unnoetig und halbiert ausserdem das Freivolumen.
Züricher Pendant
Evoluso (Zürich, echtes Bare Metal):
| Modell | CPU | RAM | Disk | EUR/Monat |
|---|---|---|---|---|
| CH-1 | Ryzen 9 7900, 12C/24T (bis 5.4 GHz) | 32 GB DDR5 | 1 TB NVMe | 199 |
| CH-2 | EPYC 7282 Rome, 16C | 64 GB DDR4 | 1 TB NVMe | 219 |
| CH-3 | EPYC 7443P Milan, 24C | 128 GB DDR4 | 2 TB NVMe | 299 |
Nur CH-1 kommt in Frage: die beiden EPYC-Varianten sind Zen 2 bzw. Zen 3 mit niedrigem Takt und würden sich vermutlich ähnlich verhalten wie netcup. CH-1 hat dafür nur 32 GB RAM - bei 8-10 GB pro BDD-Shard reicht das für zwei Shards damit leider nicht mehr.
Hinzu kommt dann aber noch ein Performance Impact! Auf Notebookcheck bemerkt man die deutlich geringere Taktung und den L3 Cache.
Evoluso CH-1 ist trotz des niedrigeren Preises dennoch die schlechtere Wahl:
- 12 statt 16 Kerne
- 5.4 statt 5.7 GHz Boost
- nur 64MB L3 statt 128MB
Beim 7950X3D sitzt der 3D V-Cache auf einem der beiden CCDs,
das sieht also 96 MB gegenüber 32 MB pro CCD des Ryzen 7900.
Für einen cache-gebundenen Prozess also der Faktor 3.
Genau hier ist aber unser Flaschenhals
- 46% Rueckstand beim Compressing
- nur 10% beim Decompressing.
- Dazu 32 GB RAM statt 128 GB
- (erwähenswert) nur 1 TB statt 3.8 TB NVMe.
Preisvergleich für vergleichbare Leistung:
| CPU | RAM | Disk | EUR/Monat | |
|---|---|---|---|---|
| Hetzner AX102-1 (DE) | 7950X3D, 16C/32T | 128 GB | 2x 1.92 TB | 259 |
| Evoluso CH-1 (CH) | 7900, 12C/24T | 32 GB | 1 TB | 199 |
Offene Fragen (erst nach Test)
Leistung nur extrapoliert
Die AX102-Leistung ist nicht gemessen, aber kann gut extrapoliert werden.
Der EPYC 9R14, der in Warp verwendet wird, und Hetzners 7950X3D sind beide Zen 4 und ihre threads skalieren mit dem Takt.
Aus unserer eigenen Messung (6891 MIPS @ 3.69 GHz = 1867 MIPS/GHz) ergeben sich bei 5.7 GHz rund 10.600 MIPS.
Unter Linux mit einem Ryzen 7900X3D erreiche ich sogar 11.248 MIPS, obwohl dieser gemäss GeekBench 5 um 1,9% langsamer sein soll.
Dieser Prozessor ist allerdings der kleien Bruder (4 physische Kerne weniger).
Da wir bereits Parallelisierung komplett widerlegt haben, können diese Werte als identisch betrachtet werden.
Ich erwarte daher rund 1.3 - 1.35x die Leistung von Warp pro Thread.
Wichtig: der Linux-Build von 7-Zip ist auf identischer Hardware ~23% schneller als der Windows-Build (gemssen in netcup: 5342 vs 4346 MIPS),
die 11248 MIPS dse7900X3D könnten unter Windows also gerne nur 9200 sein.
| Messung | Warp heute | AX102 erwartet |
|---|---|---|
| Schule-Shard | 11m30s | ~8m30s |
| Rest-Shard | 8m35s | ~6m20s |
| BDD-Stage | 13m20s (2x 8x) | ~9-10 min (1 Maschine) |
| ci_build (MSBuild) | 6m22s (1x 16x) | 3m |
Eine einzelne Maschine würde damit leisten, wofür heute zwei Warp-8x gebraucht werden.
Der Vorbehalt bleibt die Speicherbandbreite: zwei Shards auf einer Maschine teilen sich ~58 GB/s (Dual-Channel DDR5-3600).
Im Verlgeich hat ein EPYC-Socket zwölf Kanäle.
Falls das kracht, ergibt sich dasselbe Muster wie bei netcup:
CPU-Last steigt, aber Durchsatz fällt.
Mitigation wäre ein Shard pro Maschine, womit wir immer noch deutlich günstiger unterwegs wären als in der bisherigen Strategie.
Da wir hier aber einen Gamingprozessor haben, muss hier nicht so viel geraten werden. Meine Vermutung ist, dass da 4x32G DDR5-3600 drinstecken.
Problemkind Azure PremiumSSD
Die Azure Disk ist in ihrer Performance immer noch unter aller Kanone.
Wenn das Ding tatsächlich nur 35MB/s liefert, dann quält das unsere Entwickler und das ganze Unterfangen ist nicht mehr tragbar.
Denn dann würden sich Entwickler, Workflows und CLaude um die Bandbreite der Disk schlagen.