Bitcoin Node Sync: Wenn mehr Kerne es langsamer machen
"Wirf einfach mehr CPU-Kerne drauf." Das ist der Instinkt, wenn was langsam läuft, oder? Mehr Parallelverarbeitung, schnellere Ergebnisse.
Ich dachte genauso, als meine Bitcoin Node Background-Blöcke mit 14 Blöcken pro Sekunde validierte. Mit einer 8-Kern-CPU, die größtenteils bei 18% rumdümpelte, müsste mehr Kerne nutzen doch schneller sein?
Spoiler: Es machte die Sache 50% langsamer.
Das Experiment
Meine Node lief mit Bitcoin Knots 28.1 im AssumeUTXO-Modus und validierte historische Blöcke im Hintergrund von Block 346.000 in Richtung Snapshot-Basis bei 840.000. Die Validierung nutzte nur einen Bruchteil der verfügbaren Ressourcen:
Validierung: 14,0 Blöcke/s
Disk I/O: 7,4%
Netzwerk: 4,8%
Arbeitsspeicher: 54%
Alles wirkte unterausgelastet. Der offensichtliche Schritt: Erhöhe den
par-Parameter (der die Script-Verification-Threads steuert)
von Standard auf par=8, um alle 8 Kerne zu nutzen.
Das Ergebnis: Langsamer, nicht schneller
Nach Neustart mit par=8 und nach Stabilisierung erzählten
die Zahlen eine andere Geschichte:
CPU-Auslastung: 11,8% (↓ von 17,9%)
Validierung: 7,4 Blöcke/s (↓ von 14,0 b/s)
Die Node wurde LANGSAMER und nutzte WENIGER CPU. Was ist passiert?
Das ist kontraintuitiv. Mehr Threads sollten mehr Arbeit bedeuten, nicht weniger. Aber die Schlüsselerkenntnis: Die Threads arbeiten nicht weniger, weil sie faul sind – sie warten.
Thread Contention verstehen
Bitcoin Cores Validierungsprozess umfasst:
- Block herunterladen von Peers (sequenzielles I/O)
- Signaturen prüfen innerhalb des Blocks (parallelisierbar)
- UTXO-Datenbank aktualisieren (Random I/O, serialisiert)
- Zum nächsten Block (sequenziell)
Schritt 2 (Signaturverifikation) kann mehrere Kerne effektiv nutzen, aber der kritische Pfad ist Schritt 3: Die Chainstate-Datenbank updaten. Das ist eine LevelDB mit Millionen kleiner, zufälliger Read/Write-Operationen.
Die Chainstate-Datenbank hat inhärente Serialisierungspunkte. Mehrere Threads, die gleichzeitig darauf zugreifen, beschleunigen nichts - sie erzeugen Lock Contention. Threads verbringen Zeit mit Warten auf Datenbank-Locks statt nützliche Arbeit zu verrichten.
Was passiert mit par=8
Mit mehr aktiven Threads:
- Mehr Threads konkurrieren um dieselben Datenbank-Locks
- Context-Switching-Overhead steigt
- Threads blockieren sich gegenseitig bei
cs_main(Bitcoins globaler Lock) - CPU-Zyklen werden für Synchronisation verschwendet, nicht für Validierung
Das Ergebnis: CPU-Auslastung sinkt (Threads warten, arbeiten nicht) und Durchsatz sinkt (mehr Contention-Overhead).
Warum AssumeUTXO Background Validation Disk-gebunden ist
Während der AssumeUTXO-Hintergrundvalidierung validiert deine Node jeden Block von Genesis bis zur Snapshot-Basis (840.000 Blöcke). Das heißt:
- Über 60 Millionen UTXOs zu verfolgen
- Milliarden von Signaturverifikationen
- Hunderte GB an Chainstate-Datenbankoperationen
Forschung und Profiling zeigen konsistent: Disk I/O ist der limitierende Faktor, nicht die CPU. Selbst High-End-Hardware zeigt Disk-Lesevorgänge bei 150-220 MB/s, während CPU-Kerne bei 30% Auslastung sitzen.
"Die Gesamtgeschwindigkeit von Bitcoin Core wird erheblich durch die Random-Access-Geschwindigkeit des Chainstate-Verzeichnisses beeinflusst. Wenn dein Chainstate auf einer Magnetplatte liegt, ist das sehr wahrscheinlich dein größter Performance-Flaschenhals."
Was tatsächlich die Performance verbesserte
Nachdem ich das Problem verstanden hatte, setzte ich par auf
Standard zurück und erhöhte stattdessen dbcache von 4 GB auf 8 GB:
# bitcoin.conf
dbcache=8000 # 8 GB Cache (war 4000)
# par entfernt - Standard-Auto-Erkennung ist optimal
Die Logik: Wenn Disk I/O der Flaschenhals ist, halte mehr Daten im RAM,
um Disk-Zugriffe zu reduzieren. Der dbcache-Parameter kontrolliert,
wie viel RAM Bitcoin Core für den UTXO-Cache verwendet.
Forschung zeigt, dass eine Erhöhung von dbcache von 4 GB auf 8 GB etwa 10-24% Performance-Verbesserung bringt, abhängig von der Validierungsphase.
Noch wichtiger: Weniger Disk-Flushes = weniger I/O-Contention = geschmeidigere Validierung.
Warum Standard-par besser ist
Bitcoin Cores Standard par=0 (Auto-Erkennung) wurde nach
umfangreichen Tests gewählt. Es nutzt typischerweise Kerne - 1
Threads, begrenzt auf 15, was Parallelismus gegen Overhead ausbalanciert.
Für Disk-gebundene Workloads wie Hintergrundvalidierung sind 2-4 Script-Verification-Threads optimal. Mehr davon erzeugt abnehmende Erträge oder sogar Regression durch Contention.
Die richtige Hardware macht den Unterschied
Wenn Validierung Disk-gebunden ist, ist die Lösung nicht mehr CPU-Power - es ist schnellerer Speicher. Die Schlüsselerkenntnis:
- Chainstate-Datenbank (~15-20 GB): braucht NVMe SSD
- Block-Dateien (~600 GB): können auf langsamer HDD bleiben
Eine NVMe SSD bietet 100.000+ zufällige IOPS verglichen mit ~100 bei einer HDD. Das ist eine 1000-fache Verbesserung dort, wo es wirklich zählt.
• Chainstate auf interner NVMe SSD
• Blöcke auf externer USB HDD (günstig, Kapazität)
• 8-16 GB RAM für großen dbcache
• Jede moderne CPU (selbst alter i3 funktioniert gut)
Dieses Setup kostet €150-250 insgesamt mit gebrauchter Hardware.
Lektionen aus Real-World-Testing
Durch diese Optimierungsreise ergaben sich mehrere Schlüssellektionen:
1. Messen, nicht annehmen
Niedrige CPU-Auslastung bedeutet nicht „zu wenig Threads" - es bedeutet oft „Threads sind blockiert". Mehr Threads zu einer umkämpften Ressource hinzufügen macht es schlechter, nicht besser.
2. Verstehe deinen Flaschenhals
Bitcoin-Validierung hat verschiedene Phasen mit verschiedenen Flaschenhälsen:
- Frühe Blöcke (2009-2012): CPU-gebunden (wenige UTXOs, einfache Validierung)
- Mittlere Blöcke (2013-2017): Disk-gebunden (UTXO-Set-Wachstum)
- Neuere Blöcke (2018+): CPU-gebunden wieder (SegWit, Taproot-Komplexität)
AssumeUTXO-Hintergrundvalidierung durchläuft alle Phasen, aber der Disk-gebundene mittlere Abschnitt dominiert die Zeit.
3. Vertraue den Standards
Bitcoin Cores Standard-Einstellungen sind gut abgestimmt. Der par
-Parameter existiert für spezifische Anwendungsfälle (extrem High-End-Hardware,
oder absichtlich Kerne freilassen), nicht als „mach es schneller"-Knopf.
4. Cache ist König
Jedes Byte, das du im RAM hältst, ist ein Byte, das du nicht von
der Disk holen musst. dbcache erhöhen bringt viel mehr
als Thread-Counts zu tunen.
Die breiteren Implikationen
Dieses Muster - wo mehr Parallelismus die Performance verschlechtert - erscheint durchgehend in verteilten Systemen. Es wird Thread Contention genannt und ist eine fundamentale Herausforderung in nebenläufiger Programmierung.
Bitcoin Core-Entwickler haben hart daran gearbeitet, Contention-Punkte zu
reduzieren (lock-freie Datenstrukturen, reduzierter cs_main-Scope),
aber einige Serialisierung ist dem Problem inhärent: Man kann eine Datenbank
nicht parallel aktualisieren ohne Koordination.
Hintergrundvalidierung läuft mit niedriger Priorität per Design. Die Node ist bereits benutzbar (du kannst Transaktionen senden, neue Blöcke validieren), also keine Eile. Bitcoin Core hält dein System responsiv und vermeidet thermische Probleme auf Low-Power-Hardware.
Die Zukunft: SwiftSync
Während Bitcoin Core derzeit keine Benutzer-Controls für Background-Validation- Geschwindigkeit bietet, gibt es eine vielversprechende Entwicklung, die die Gleichung grundlegend ändern wird: SwiftSync.
Was ist SwiftSync?
SwiftSync ist eine vorgeschlagene Optimierung, die "Hints-Dateien" (~88-100 MB komprimiert) verwendet, um anzuzeigen, welche UTXOs bei bestimmten Block-Höhen noch unverbraucht sind. Dies ermöglicht nahezu zustandslose, vollständig parallelisierbare Validierung.
SwiftSync hat eine 5,28-fache Beschleunigung des Initial Block Downloads im Vergleich zu Standard-Bitcoin-Core-Einstellungen gezeigt:
• Standard IBD: ~41 Stunden
• Mit SwiftSync: ~8 Stunden
Die Beschleunigung resultiert aus der Eliminierung unnötiger Datenbank-Schreibvorgänge für temporäre UTXOs, die innerhalb des Sync-Fensters erstellt und ausgegeben werden.
Auswirkung auf Background-Validation
Wichtig: SwiftSync beschleunigt nicht nur den initialen Sync - es beschleunigt auch die AssumeUTXO-Hintergrundvalidierung. Als James O'Beirne fragte, ob SwiftSync überhaupt nötig sei, da AssumeUTXO bereits einen schnellen Weg zur Nutzbarkeit bietet, stellte Entwickler Ruben Somsen klar:
"SwiftSync beschleunigt die Hintergrundvalidierung von assumeUTXO und ist damit eine nette Ergänzung für Nutzer von assumeUTXO."
Das bedeutet, dass meine 23-Stunden-Schätzung für Background-Validation potenziell auf 4-5 Stunden mit SwiftSync fallen könnte - ohne zusätzliche Hardware oder Konfigurationsänderungen.
Aktueller Status
Ab 2025 existiert SwiftSync als Proof-of-Concept-Implementierung in Rust, mit aktiver Entwicklung und Tests, die vielversprechende Ergebnisse zeigen. Jedoch:
- Es ist noch nicht in Bitcoin Core integriert
- Kein Zeitplan für Mainnet-Release wurde angekündigt
- Community-Diskussion über optimale Implementierung läuft weiter
Vorerst bleiben die zuvor diskutierten Optimierungen (NVMe-Speicher, großer dbcache, Standard-par-Einstellungen) der beste Ansatz. Aber SwiftSync repräsentiert eine spannende Zukunft, in der Hintergrundvalidierung viel schneller abgeschlossen wird, ohne die derzeit erforderlichen Hardware-Investitionen.
Praktische Empfehlungen
Wenn du eine Bitcoin Node betreibst und optimale Performance willst:
- NVMe für Chainstate nutzen - nicht verhandelbar für gute Performance
- dbcache erhöhen - 50% des verfügbaren RAM sind safe
- par bei Standard lassen - oder
par=-2um 2 Kerne freizulassen - Geduld haben - Hintergrundvalidierung dauert Tage by design
Beispiel-Konfiguration für 16 GB RAM System:
# bitcoin.conf
dbcache=8000 # 8 GB Cache
maxmempool=300 # 300 MB Mempool
par=0 # Auto-Erkennung (Standard)
# oder: par=-2 # Lasse 2 Kerne frei
Fazit
Die Intuition, dass „mehr Kerne = schneller" bricht zusammen, wenn die Workload durch eine serialisierte Ressource wie Disk I/O begrenzt ist. In Bitcoins Fall erzeugt das Draufwerfen von mehr Threads auf Hintergrundvalidierung Contention, die tatsächlich verlangsamt.
Die echten Optimierungen sind:
- ✅ Schneller Speicher (NVMe) für den kritischen Pfad
- ✅ Großer Cache (dbcache) um Disk-Zugriffe zu minimieren
- ✅ Standard-Thread-Einstellungen, die Contention vermeiden
- ❌ Nicht mehr CPU-Kerne hinzufügen
- ❌ Nicht Thread-Counts über Standards erhöhen
Verstehen, wo der wahre Flaschenhals deines Systems liegt - und den angehen statt Annahmen zu folgen - das ist der Schlüssel zu echten Performance-Verbesserungen.
Hilfe bei Node-Optimierung?
Ich richte Bitcoin Nodes auf Custom-Hardware ein und optimiere sie - abgestimmt auf deinen spezifischen Use-Case. Von Home-Mining-Wärmeintegration bis High-Performance-Validierungs-Rigs.
Melde dich