Gameserverprestaties: bare metal vs virtuele machines
Bare metal wint op de twee getallen die bepalen of een gameserver goed aanvoelt: de worst-case ticktijd en de worst-case latency. Een single-tenant VM op hardware die je zelf beheert, komt dicht in de buurt. Bij een overboekte multi-tenant VPS valt fixed-tick simulatie uit elkaar, want een vCPU die een paar milliseconden te laat wordt ingepland, is een gemiste tick die elke speler ziet als rubberbanding. Deze gids behandelt wat een hypervisor toevoegt aan een tick-loop, waarom de 95e-percentiel ticktijd belangrijker is dan de gemiddelde doorvoer, hoe je steal time en MSPT op je eigen server meet, en wanneer een VM nog steeds de juiste keuze is.
Loading...
Het korte antwoord
Bare metal wint op de twee getallen die bepalen of een gameserver goed aanvoelt: de worst-case ticktijd en de worst-case latency. Een single-tenant virtuele machine op hardware die je zelf beheert, komt zo dicht in de buurt dat de meeste spelers nooit het verschil zullen merken. Bij een overboekte multi-tenant VPS, het soort dat het goedkope segment van gamehosting vult, loopt het spaak, want wat een hypervisor doet onder contentie (je CPU op zijn beurt laten wachten) is precies wat een fixed-tick game-loop niet kan opvangen.
Dat is het hele argument in één alinea. Een gameserver wordt niet beoordeeld op hoeveel werk hij per seconde verzet; hij wordt beoordeeld op de vraag of elke afzonderlijke tick binnen zijn budget klaar is. Mis één tick en elke verbonden speler ziet het: rubberbanding, een hit die niet registreerde, een rollback. Gemiddelde doorvoer kan er perfect uitzien terwijl het slechtste procent van de ticks in stilte de wedstrijd verpest. Virtualisatie voegt variantie toe aan precies dat slechtste procent, en goedkope virtualisatie voegt er veel van toe.
De eerlijke positie is dus voorwaardelijk, niet tribaal. Bare metal is de veilige standaard voor alles wat competitief of druk is. Een VM is prima, soms zelfs de betere keuze, wanneer je zelf de hypervisor bezit en bepaalt wie er nog meer op de machine draait. Een gedeelde VPS van een host die vier keer meer vCPU's verkoopt dan hij cores heeft, is de opzet die de "waarom lagt mijn server"-topics oplevert. Dit artikel legt het mechanisme achter beide situaties uit, en laat zien hoe je meet in welke situatie jij je eigenlijk bevindt.
Deze gids behandelt:
- wat een hypervisor toevoegt aan een tick-loop: vCPU-scheduling, steal time, timerjitter, NUMA en I/O-paden
- waarom fixed-tick simulatie om de 95e-percentiel tick geeft, niet om het gemiddelde
- de overboekingseconomie waardoor goedkope VPS-gamehosting lag geeft
- hoe je steal time en ticktijd op je eigen server meet, met echte commando's
- waarom containers geen VM's zijn, en wanneer een VM echt het juiste gereedschap is
Voor het bredere verhaal (managed hosting versus je eigen machine draaien, en de hardware kiezen) is de bare-metal gids voor gamehosting het hoofdartikel waar dit artikel onder valt.
Wat een hypervisor daadwerkelijk toevoegt
Begin met de vriendelijke versie. Een moderne hypervisor zoals KVM voert gastinstructies van de CPU uit op de echte processor met hardwareondersteuning (VT-x of AMD-V). Voor pure rekenkunde draait een VM binnen een paar procent van native, en als een gameserver CPU-gebonden was in de zin van "een grote array doorrekenen", zou virtualisatie nauwelijks uitmaken. Dat is hij niet, en dat is het probleem. Een gameserver is latency-gebonden op een herhalend schema, en de hypervisor zit tussen dat schema en de hardware. Dit is wat hij toevoegt.
vCPU-scheduling en steal time. De virtuele CPU's van je VM zijn geen CPU's; het zijn threads die de host-scheduler draait op echte cores wanneer hij daartoe besluit. Als de host bezig is met andere guests, hostprocessen of interrupts, staat je vCPU in een wachtrij te wachten op een fysieke core. Die wachttijd is CPU steal time, gerapporteerd als %st of st in top, vmstat en mpstat. Het is tijd waarin je game-loop de CPU wilde en niet kreeg. Op een machine met genoeg cores voor elke guest blijft het dicht bij nul; bij overboeking loopt het op, en elke millisecunde steal is een millisecunde die je tick te laat was. Leaseweb's analyse van steal time hanteert als vuistregel dat aanhoudende steal boven de 10 procent betekent dat de guest langzamer draait dan zou moeten.
Timer- en interruptjitter. Een game-loop wordt 20 of 64 keer per seconde gewekt door een timer. Onder virtualisatie wordt die timerinterrupt zelf bemiddeld door de hypervisor, die aan elke wake-up een kleine, variabele vertraging toevoegt. Op een inactieve host is die vertraging verwaarloosbaar. Onder belasting kan de wake-up milliseconden verschuiven, en een loop die te laat wakker wordt, is ook te laat klaar.
NUMA-effecten. Op een server met twee sockets is geheugen dat aan de ene socket vastzit, trager te bereiken vanaf de andere. Als de hypervisor je vCPU's op de ene socket plant terwijl het geheugen van je VM op de andere staat, betaalt elke toegang de cross-node-penalty. Bare metal heeft dezelfde fysica, maar het besturingssysteem ziet de echte topologie en plaatst threads daarop; een VM ziet vaak een afgevlakte, synthetische topologie, tenzij de host bewust de echte topologie blootlegt.
Memory ballooning. Het virtio-balloon-apparaat laat de host RAM terugvorderen van een guest door er een "ballon" in op te blazen. Handig voor dichtheid, vijandig voor een gameserver: als de host het geheugen terugpakt dat je JVM of gameproces gebruikte, krijg je swapping of garbage-collection-druk op het slechtst mogelijke moment. Op overboekte hosts is ballooning hoe een provider meer guests laat passen dan er RAM voor is.
virtio-I/O-paden. Schijf en netwerk lopen via paravirtualiseerde drivers (virtio-blk en virtio-net, meestal met vhost). Die zijn snel; ze zijn niet gratis. Elk pakket en elke schijflezing steekt één grens meer over dan op bare metal. Voor een Minecraft-wereld die chunks laadt, of een drukke server die logs en world saves wegschrijft, verschijnt dat extra padstuk als incidentele I/O-stalls die een tick oprekken. Dezelfde VirtIO-tol komt vanuit de containerhoek aan bod in onze vergelijking tussen LXC en KVM.
Elk afzonderlijk zijn dit kleine dingen. Het probleem is dat ze allemaal op hetzelfde slachtoffer landen: de tick die binnen 50 milliseconden klaar moet zijn, of 15.
Waarom alleen de slechtste tick telt
Een Minecraft-server tickt 20 keer per seconde, wat elke tick 50 milliseconden geeft om alles te doen: mob-AI, redstone, blokupdates, entiteitsbeweging, en dan de wereld naar elke speler sturen. Blijf binnen het budget en de server houdt 20 TPS aan. Overschrijd het en de tick duurt te lang, de volgende begint te laat, en de tijd op de server vertraagt voor iedereen tegelijk. CS2 draait zijn simulatie op 64 tick, ongeveer 15.6 milliseconden per tick, met een subtick-systeem dat inputs tussen ticks in van een tijdstempel voorziet, zodat een schot landt waar het werd afgevuurd. Een trage tick vertraagt nog steeds het moment waarop die inputs worden verwerkt.
Hier zit het deel dat capaciteitsplanning laat struikelen: dit zijn worst-case problemen, geen gemiddelde. Een server kan gemiddeld 19.9 TPS halen en toch vreselijk aanvoelen omdat een tick één keer per seconde 180 milliseconden duurt. Gemiddelden verbergen dat; percentielen niet. Het bruikbare getal is de 95e-percentiel ticktijd (p95), niet het gemiddelde, want dat vertelt je hoe je trage ticks eruitzien, en de trage ticks zijn wat spelers voelen.
Een hypervisor die hier 8 milliseconden steal toevoegt en daar een schedulingvertraging van 12 milliseconden, zal je gemiddelde nauwelijks verschuiven. Hij verwoest wel je p95. Dat is precies de reden waarom bare metal en een goed beheerde VM dezelfde gemiddelde TPS kunnen noteren terwijl ze compleet anders aanvoelen in een vuurgevecht. Het gemiddelde zegt "prima"; het 95e percentiel zegt "hapert onder belasting", en slechts een van de twee is wat spelers daadwerkelijk ervaren.
Overboeking: waarom goedkope VPS-gamehosting lag geeft
De economie van budget-VPS-hosting is simpel, en ze werkt tegen je. Een host heeft een machine met, zeg, 32 fysieke cores. Eerlijk verkocht als dedicated cores is dat een vast aantal klanten. Verkocht als vCPU's met een overboeking van 4:1, is het 128 vCPU's aan abonnementen op dezelfde silicium. Meestal zijn de meeste guests inactief, dus de rekensom klopt en de host verdient geld.
Op het moment dat een paar van je buren tegelijk actief worden (een back-upjob, een andere gameserver die volloopt, iemand die een compile start), heeft de host-scheduler meer draaibare vCPU's dan cores, en laat hij die van jou wachten. Die wachttijd is de steal time uit de vorige sectie, en je hebt er geen controle over, want de contentie komt van klanten die je niet kunt zien. Dit is het probleem van de luidruchtige buur, en voor een fixed-tick workload is het bijna een worst case: je tickbudget ligt vast op 50 of 15 milliseconden, maar de CPU-tijd die je daadwerkelijk krijgt, is nu een loterij die door de belasting van anderen wordt bepaald. Het is ook waarom een VPS om 3 uur 's nachts prachtig kan benchmarken en tijdens piekbelasting onderuitgaat, op hetzelfde abonnement, zonder dat er aan jouw kant iets is veranderd.
Hoe je het op je eigen server meet
Genoeg theorie. Dit is hoe je uitzoekt of virtualisatie je daadwerkelijk iets kost, op de machine die je hebt.
Steal time. Draai top en lees het st-cijfer af op de %Cpu(s)-regel:
%Cpu(s): 42.1 us, 3.2 sy, 0.0 ni, 38.0 id, 0.0 wa, 0.0 hi, 1.1 si, 15.6 st
De 15.6 st is het getal dat ertoe doet: 15.6 procent van de tijd wilde deze vCPU draaien en kon dat niet, omdat de host elders bezig was. vmstat 1 zet hetzelfde cijfer elke seconde in zijn meest rechtse st-kolom, en mpstat -P ALL 1 splitst %steal uit per core:
vmstat 1
mpstat -P ALL 1
Op bare metal is st altijd 0, want er is geen hypervisor om van te stelen, en dat is zelf al de tell. Zie je enige steal, dan zit je op een guest; zie je aanhoudende dubbelcijferige steal, dan is je host overboekt. Deze output is ter illustratie. Jouw waarden verschillen met hardware, belasting en hoe druk je buren zijn.
Minecraft-ticktijd. Installeer de spark-profiler (een plugin of mod, afhankelijk van je serversmaak) en draai /spark tps. Spark rapporteert TPS tegen het doel van 20, en tickduur tegen het budget van 50 milliseconden, en geeft je de minimum-, mediane, 95e-percentiel- en maximum-MSPT:
/spark tps
TPS from last 5s, 10s, 1m, 5m, 15m:
17.9, 18.8, 19.7, 20.0, 20.0
Tick durations (min/med/95%ile/max ms) from last 10s, 1m:
22/47/96/210; 20/43/71/180
Let op de 95%ile-kolom, niet de mediaan. Een mediaan van 47 milliseconden met een 95e percentiel van 96 is een server die er gemiddeld gezond uitziet en hapert onder belasting. Op een overboekte guest lopen dat 95e-percentielcijfer en je steal time samen op, en zo koppel je het symptoom precies aan de oorzaak. /spark health geeft dezelfde TPS en MSPT samen met CPU en geheugen in één momentopname. (Output representatief.)
Source- en CS2-servers. Het stats-consolecommando toont CPU-gebruik en een fps-cijfer dat de tickrate volgt: een gezonde 64-tick-server rapporteert fps op of net boven 64, begrensd door de tickrate, en elke dip onder belasting is een frame dat de simulatie niet op tijd kon afronden. Draai het een paar keer achter elkaar om de variantie te zien, want één regel is maar een momentopname.
De schoonste manier om de kosten van de hypervisor te isoleren, is alles verder gelijk te houden: dezelfde CPU, hetzelfde RAM, dezelfde gameversie, dezelfde belasting, en alleen te veranderen of de server op bare metal draait of in een KVM-guest op diezelfde identieke hardware. Dat is een test die de moeite waard is om in een gecontroleerd lab te draaien in plaats van vanuit eerste principes te beargumenteren.
Het punt waar een meting een cijfer op zou plakken, is niet controversieel: op identieke hardware houdt de bare-metal-run een lagere en vlakkere 95e-percentiel ticktijd aan, en het nadeel van de guest groeit met de belasting. Wat een benchmark vaststelt, is hoe groot het gat is op een single-tenant VM die je zelf beheert, wat meestal klein is, tegenover wat overboeking ermee doet, wat dat niet is.
Containers zijn geen virtuele machines
Veel van de "moet ik virtualiseren"-onzekerheid verdwijnt zodra je containers en VM's uit elkaar haalt, want het is niet dezelfde afweging. Een LXC-systeemcontainer of een Docker-container deelt de kernel van de host. Er is geen guest-kernel, geen virtuele hardware, en geen laag voor vCPU-scheduling tussen jouw proces en de core. Dat betekent dat er nauwelijks steal time is en geen timervirtualisatie-jitter: een gecontaineriseerde gameserver op bare metal draait op vrijwel native snelheid, met een cgroup die begrenst hoeveel CPU en geheugen hij mag gebruiken. De overhead is een afrondingsfout.
Dus "ik wil meerdere geïsoleerde gameservers op één machine draaien" vereist geen VM's. Containers geven je resourcelimieten per server, nette verpakking en bijna-native prestaties op dezelfde kernel, precies wat een gamepanel zoals Pterodactyl onder de motorkap doet. De afwegingen die wel bestaan (zwakkere isolatie dan een VM, een gedeelde kernel, geen live migration) gaan over beveiliging en operations, niet over tickprestaties, en die behandelen we volledig in LXC vs KVM in Proxmox. Voor pure gameserverprestaties is een container op bare metal de bijna-native optie; een VM is degene die de schedulinglaag toevoegt waar dit hele artikel over gaat.
Wanneer een VM de juiste keuze is
Virtualisatie is niet de vijand; overboeking wel. Er zijn echte gevallen waarin een VM het juiste gereedschap is, en ze delen één kenmerk: jij beheerst de contentie.
- Dev-, staging- en testservers. Niemands competitieve ervaring hangt af van de p95-tick van een stagingmachine. Zet vrijelijk VM's op; de isolatie en het gemak van snapshots zijn meer waard dan de laatste paar milliseconden.
- Kleine of casual servers. Een survivalserver voor jou en een stuk of twaalf vrienden brengt de meeste ticks ruim binnen budget door. Er is zoveel speelruimte dat de overhead van de hypervisor nooit de bottleneck wordt, en een bescheiden VM is prima.
- Een VM op je eigen hypervisor. Dit is de belangrijke. Als je een hele bare-metal machine huurt en er je eigen hypervisor op draait, bepaal jij hoeveel guests de cores delen en of ze overboekt zijn. Pin de game-VM op dedicated cores, wijs niet te veel vCPU's toe, en je krijgt het grootste deel van de flexibiliteit van virtualisatie met steal time die je zelf beheerst in plaats van steal time die je host je oplegt. Het verschil tussen dit en een goedkope VPS zit volledig in wie de overboekingsbeslissing neemt.
De opzet om te vermijden voor alles wat druk of competitief is, is die waarbij iemand anders die beslissing voor je heeft genomen, en die agressief geprijsd heeft.
Als je toch moet virtualiseren: tuning die helpt
Gegeven een VM op hardware die je zelf beheert, halen een paar instellingen het grootste deel van de verloren worst-case-prestaties terug:
- Pin vCPU's aan fysieke cores. CPU-pinning (
vcpupinin libvirt) bindt de vCPU's van de game-VM aan specifieke fysieke cores, zodat de scheduler stopt ze rond te laten stuiteren. Dat vermindert jitter en verbetert het cachegedrag. Deel die vastgepinde cores niet met andere guests. - Gebruik het host-CPU-model. Zet de guest op
host-passthrough(of op zijn minsthost-model) zodat de VM de echte CPU en zijn volledige instructieset ziet, in plaats van een kleinste-gemene-deler-model dat prestaties laat liggen. - Overboek niet de cores die ertoe doen. Match vCPU's met echte cores voor de game-VM, en houd het totale toegewezen aantal vCPU's op of onder het aantal fysieke cores wanneer tickstabiliteit ertoe doet. De dichtheid die je opgeeft, is de latency die je behoudt.
- Zet ballooning uit voor de game-VM. Geef hem een vaste geheugenreservering zodat de host niet midden in een wedstrijd RAM kan terugvorderen. Laat ballooning gelden voor guests die dat wel kunnen verdragen.
- Houd de snelle NIC- en schijfpaden aan. Gebruik virtio met vhost-net, en zet gamestate op NVMe. De dimensioneringskant hiervan staat in de gids voor serverdimensionering, die ook het argument maakt voor minder, snellere cores boven veel trage.
Niets hiervan zorgt dat een VM bare metal verslaat. Het dicht het gat tot het punt waarop, op een machine die je zelf beheert, het verschil voor de meeste servers ophoudt ertoe te doen.
Het oordeel, per situatie
| Situatie | Beste keuze | Waarom |
|---|---|---|
| Competitieve shooter (CS2 en vergelijkbare) | Bare metal | Tickbudget onder 16 ms laat geen ruimte voor steal of jitter |
| Drukke publieke Minecraft of grote modpack | Bare metal | Tickbudget krap onder entiteit- en redstonebelasting; p95 is leidend |
| Kleine SMP- of vriendenserver | VM is prima | Ruime tickmarge absorbeert de overhead |
| Dev, staging of test | VM op je eigen hypervisor | Snapshots en isolatie wegen zwaarder dan de laatste paar milliseconden |
| Meerdere servers op één eigen machine | Containers op bare metal | Bijna-native, limieten per server, geen vCPU-laag |
| VM op een hypervisor die je zelf bezit | Prima indien getuned | Pin cores, niet overcommitten; jij beheerst de contentie |
| Goedkope overboekte multi-tenant VPS | Vermijden voor alles wat druk is | Steal time bepaald door buren die je niet kunt zien |
Latency is de andere helft van "goed aanvoelen", en dat gaat vooral over geografie en routering, niet over de vraag metal-versus-VM; de gids over gameserverlatency behandelt dat aspect.
Uitrollen op Serverside
Als de workload competitief of druk is, wijst het bovenstaande argument één kant op: de hele machine, zonder hypervisor tussen jouw tick-loop en de cores. Een Serverside-gameserver is single-tenant bare metal op ons eigen netwerk (AS55285), dus is er geen steal time, geen luidruchtige buren, en geen overboeking die door iemand anders dan jij wordt bepaald. Provisioning duurt minder dan een minuut, en altijd-actieve DDoS-mitigatie zit voor de publieke interface, wat voor een gameserver niet optioneel is. Wil je liever zelf één machine in VM's opdelen, dat kan ook: huur de dedicated hardware, draai je eigen hypervisor, en jij beheerst elke contentiebeslissing waar dit artikel je op wees te letten.
Veelgestelde vragen
Voegt een VM altijd lag toe aan een gameserver?
Nee. Een VM op hardware die je zelf beheert, met vastgepinde vCPU's en zonder overboeking, voegt overhead toe die klein genoeg is dat de meeste servers er nooit iets van merken. De lag die mensen aan "virtualisatie" wijten, komt vrijwel altijd door overboeking en niet door de hypervisor zelf: een gedeelde VPS waarbij je CPU-tijd afhangt van de belasting van andere klanten. Het onderliggende mechanisme is CPU steal time, en je kunt het direct meten.
Wat is CPU steal time en welk getal is slecht?
Steal time (%st in top) is het percentage van de tijd dat je virtuele CPU klaarstond om te draaien maar moest wachten tot de host een fysieke core toewees. Op bare metal is dit altijd nul. Op een gezonde VM blijft het dicht bij nul. Een veelgebruikte vuistregel is dat aanhoudende steal boven de 10 procent betekent dat de guest langzamer draait dan zou moeten, en bij een fixed-tick gameserver is zelfs een paar procent al zichtbaar als trage ticks.
Waarom geeft mijn VPS-gameserver lag terwijl het CPU-gebruik laag lijkt?
Omdat CPU-gebruik binnen de guest geen contentie op de host laat zien. Je server kan op 30 procent CPU staan en toch ticks missen als de host je virtuele CPU steeds laat wachten; die verloren tijd verschijnt als steal, niet als gebruik. Controleer de st-kolom in top of vmstat 1. Hoge steal met laag gebruik is de klassieke signatuur van een overboekte VPS.
Zijn containers beter dan VM's voor gameserverprestaties?
Voor pure prestaties wel. Een Docker- of LXC-container op bare metal deelt de kernel van de host, dus is er geen laag voor vCPU-scheduling en geen steal time, en draait hij op bijna-native snelheid. VM's bieden sterkere isolatie en functies zoals live migration die containers niet hebben. Voor tickprestaties wint een container op bare metal het van een VM; voor het isoleren van onvertrouwde klanten wint een VM. Onze vergelijking tussen LXC en KVM behandelt de volledige afweging.
Hoe meet ik of virtualisatie mijn server schaadt?
Twee getallen. Voor steal time draai je top, vmstat 1 of mpstat -P ALL 1 en lees je de st- of %steal-kolom af. Voor tickgezondheid op Minecraft installeer je de spark-profiler en draai je /spark tps, waarbij je let op de 95e-percentiel MSPT in plaats van het gemiddelde. Op Source- en CS2-servers rapporteert het stats-commando een fps-cijfer dat de tickrate volgt. Als steal time en de 95e-percentiel ticktijd samen oplopen, ligt het probleem bij de host.

Geschreven door
CEO, Serverside.com & Host Havoc
Clay is the CEO of Serverside.com and Host Havoc, with more than a decade of experience running globally distributed hosting infrastructure and a game-server platform that has served over 200,000 customers.
Verder lezen
Alle artikelen bekijkenVond je dit artikel interessant?
Ontvang nieuwe handleidingen en technische artikelen in je inbox. Geen spam, altijd uitschrijfbaar.



