Rendimiento de servidores de juego: bare metal frente a máquinas virtualesVolver

Rendimiento de servidores de juego: bare metal frente a máquinas virtuales

El bare metal gana en las dos cifras que deciden si un servidor de juego se siente bien: el tiempo de tick en el peor caso y la latencia en el peor caso. Una VM de un solo inquilino en hardware que controlas se acerca. Donde la simulación de tick fijo se viene abajo es en un VPS multiinquilino sobrevendido, porque un vCPU planificado unos milisegundos tarde es un tick perdido que todos los jugadores ven como rubber-banding. Esta guía explica qué añade un hipervisor a un bucle de tick, por qué el tiempo de tick en el percentil 95 importa más que el rendimiento medio, cómo medir el steal time y el MSPT en tu propio servidor, y cuándo una VM sigue siendo la opción correcta.

Cargando...

La respuesta corta

El bare metal gana en las dos cifras que deciden si un servidor de juego se siente bien: el tiempo de tick en el peor caso y la latencia en el peor caso. Una máquina virtual de un solo inquilino en hardware que controlas se acerca lo suficiente como para que la mayoría de los jugadores nunca noten la diferencia. Un VPS multiinquilino sobrevendido, el tipo que llena la gama barata del hosting de juegos, es donde todo se desmorona, porque lo que hace un hipervisor bajo contención (hacer que tu CPU espere su turno) es exactamente lo que un bucle de juego de tick fijo no puede absorber.

Ese es todo el argumento en un párrafo. A un servidor de juego no se le juzga por cuánto trabajo saca adelante en un segundo; se le juzga por si cada tick termina dentro de su presupuesto. Se pierde un tick y todos los jugadores conectados lo ven: rubber-banding, un impacto que no se registra, un retroceso. El rendimiento medio puede parecer perfecto mientras el peor uno por ciento de los ticks arruina la partida sin hacer ruido. La virtualización añade varianza justo a ese peor uno por ciento, y la virtualización barata añade mucha.

Así que la postura honesta es condicional, no de bando. El bare metal es la opción segura por defecto para todo lo competitivo o con mucho tráfico. Una VM está bien, y a veces es mejor, cuando el hipervisor es tuyo y decides quién más se ejecuta en la máquina. Un VPS compartido de un proveedor que vende cuatro veces más vCPU que núcleos tiene es la configuración que genera los hilos de «por qué mi servidor va con lag». Este artículo explica el mecanismo detrás de cada caso y te enseña a medir en cuál te encuentras.

Esta guía cubre:

  • qué añade un hipervisor a un bucle de tick: planificación de vCPU, steal time, jitter de temporizadores, NUMA y rutas de E/S
  • por qué a la simulación de tick fijo le importa el tick del percentil 95, no la media
  • la economía de la sobresuscripción que hace que el hosting de juegos en VPS barato vaya con lag
  • cómo medir el steal time y el tiempo de tick en tu propio servidor, con comandos reales
  • por qué los contenedores no son VM, y cuándo una VM es la herramienta adecuada

Para el marco más amplio (hosting gestionado frente a tener tu propia máquina, y cómo elegir el hardware), la guía de hosting de juegos en bare metal es el artículo principal del que depende este.

Qué añade un hipervisor

Empecemos por la versión amable. Un hipervisor moderno como KVM ejecuta las instrucciones de CPU del invitado en el procesador real con asistencia por hardware (VT-x o AMD-V). En cálculo bruto, una VM rinde a pocos puntos porcentuales del nativo, y si un servidor de juego estuviera limitado por CPU en el sentido de «procesar un array enorme», la virtualización apenas importaría. No lo está, y ahí está la trampa. Un servidor de juego está limitado por la latencia en un calendario que se repite, y el hipervisor se sitúa entre ese calendario y el hardware. Esto es lo que mete en medio.

Planificación de vCPU y steal time. Las CPU virtuales de tu VM no son CPU; son hilos que el planificador del host ejecuta en núcleos reales cuando él decide. Cuando el host está ocupado con otros invitados, procesos propios o interrupciones, tu vCPU espera en una cola de ejecución a que quede libre un núcleo físico. Esa espera es el steal time de CPU, que aparece como %st o st en top, vmstat y mpstat. Es tiempo en que tu bucle de juego quería la CPU y no la tuvo. En una máquina con núcleos suficientes para todos los invitados se queda cerca de cero; con sobresuscripción sube, y cada milisegundo de steal es un milisegundo de retraso en tu tick. El análisis del steal time de Leaseweb sitúa la regla práctica en que un steal sostenido por encima del 10 por ciento significa que el invitado va más lento de lo que debería.

Jitter de temporizadores e interrupciones. Un bucle de juego se despierta con un temporizador 20 o 64 veces por segundo. Con virtualización, esa interrupción de temporizador pasa a su vez por el hipervisor, que añade pequeños retrasos variables a cada despertar. En un host inactivo el retraso es despreciable. Bajo carga, el despertar puede desviarse varios milisegundos, y un bucle que se despierta tarde termina tarde.

Efectos NUMA. En un servidor de dos sockets, la memoria conectada a un socket es más lenta de alcanzar desde el otro. Si el hipervisor planifica tus vCPU en un socket mientras la memoria de tu VM está en el otro, cada acceso paga la penalización entre nodos. El bare metal tiene la misma física, pero el sistema operativo ve la topología real y coloca los hilos en consecuencia; una VM suele ver una topología aplanada y sintética, salvo que el host exponga la real a propósito.

Memory ballooning. El dispositivo virtio-balloon permite al host recuperar RAM de un invitado inflando un «globo» dentro de él. Útil para la densidad, hostil para un servidor de juego: si el host recupera memoria que usaba tu JVM o tu proceso de juego, tienes swap o presión sobre el garbage collection en el peor momento posible. En hosts sobrevendidos, el ballooning es la forma en que un proveedor mete más invitados de los que caben en su RAM.

Rutas de E/S virtio. El disco y la red pasan por drivers paravirtualizados (virtio-blk y virtio-net, normalmente con vhost). Son rápidos, pero no gratis. Cada paquete y cada lectura de disco cruzan una frontera más que en bare metal. En un mundo de Minecraft que carga chunks, o en un servidor con mucha actividad que escribe logs y guardados del mundo, esa ruta más larga se nota en bloqueos de E/S ocasionales que alargan un tick. El mismo peaje de VirtIO se trata desde el lado de los contenedores en nuestra comparativa LXC vs KVM.

Por separado, cada uno es pequeño. El problema es que todos caen sobre la misma víctima: el tick que tiene que terminar en 50 milisegundos, o en 15.

Por qué solo importa el peor tick

Un servidor de Minecraft hace 20 ticks por segundo, lo que da a cada tick 50 milisegundos para hacerlo todo: IA de los mobs, redstone, actualizaciones de bloques, movimiento de entidades y, después, enviar el mundo a cada jugador. Si te mantienes dentro del presupuesto, el servidor sostiene 20 TPS. Si te pasas, el tick se alarga, el siguiente empieza tarde y el tiempo del servidor se ralentiza para todos a la vez. CS2 ejecuta su simulación a 64 ticks, unos 15,6 milisegundos por tick, con un sistema de subtick que marca con hora las entradas entre ticks para que un disparo impacte donde se hizo. Un tick lento sigue retrasando el momento en que se procesan esas entradas.

Aquí está lo que confunde a la planificación de capacidad: son problemas de peor caso, no de media. Un servidor puede tener una media de 19,9 TPS y sentirse fatal porque una vez por segundo un tick tarda 180 milisegundos. Las medias lo ocultan; los percentiles, no. La cifra útil es el tiempo de tick del percentil 95 (p95), no la media, porque te dice cómo son tus ticks lentos, y los ticks lentos son los que notan los jugadores.

Un hipervisor que añade 8 milisegundos de steal aquí y un retraso de planificación de 12 milisegundos allá apenas moverá tu media. Destrozará tu p95. Esa es toda la razón por la que el bare metal y una VM bien gestionada pueden mostrar el mismo TPS medio y sentirse completamente distintos en pleno tiroteo. La media dice «bien»; el percentil 95 dice «tirones bajo carga», y solo uno de los dos es lo que viven los jugadores.

Sobresuscripción: por qué el hosting de juegos en VPS barato va con lag

La economía del hosting VPS barato es sencilla, y juega en tu contra. Un proveedor tiene una máquina con, pongamos, 32 núcleos físicos. Vendida honestamente como núcleos dedicados, da para un número fijo de clientes. Vendida como vCPU con una sobresuscripción de 4:1, son 128 vCPU en planes sobre el mismo silicio. Casi siempre, casi todos los invitados están inactivos, así que las cuentas salen y el proveedor gana dinero.

En cuanto varios de tus vecinos se ponen a trabajar a la vez (una copia de seguridad, otro servidor de juego que se llena, alguien que lanza una compilación), el planificador del host tiene más vCPU listos para ejecutarse que núcleos, y hace esperar al tuyo. Esa espera es el steal time de la sección anterior, y no tienes ningún control sobre ella, porque la contención viene de inquilinos que no ves. Es el problema del vecino ruidoso, y para una carga de tick fijo está cerca del peor caso: tu presupuesto de tick está fijado en 50 o 15 milisegundos, pero el tiempo de CPU que recibes pasa a ser una lotería que decide la carga de otros. También es la razón por la que un VPS puede dar un benchmark precioso a las 3 de la madrugada y hundirse en hora punta, con el mismo plan y sin que hayas cambiado nada.

Cómo medirlo en tu propio servidor

Basta de teoría. Así puedes saber si la virtualización te está costando algo, en la máquina que tienes.

Steal time. Ejecuta top y lee el valor st en la línea %Cpu(s):

%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

El 15.6 st es la cifra que importa: el 15,6 por ciento del tiempo, este vCPU quería ejecutarse y no pudo, porque el host estaba ocupado con otra cosa. vmstat 1 muestra la misma cifra en su columna st, la de más a la derecha, una vez por segundo, y mpstat -P ALL 1 desglosa %steal por núcleo:

vmstat 1
mpstat -P ALL 1

En bare metal, st siempre es 0, porque no hay hipervisor que robe tiempo, y eso ya es una pista en sí. Si ves algo de steal, estás en un invitado; si ves un steal sostenido de dos cifras, tu host está sobresuscrito. Estas salidas son ilustrativas. Tus valores variarán según el hardware, la carga y lo ocupados que estén tus vecinos.

Tiempo de tick en Minecraft. Instala el profiler spark (un plugin o un mod, según la variante de tu servidor) y ejecuta /spark tps. Spark informa del TPS frente al objetivo de 20 y de la duración de los ticks frente al presupuesto de 50 milisegundos, con el MSPT mínimo, mediano, del percentil 95 y máximo:

/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

Fíjate en la columna 95%ile, no en la mediana. Una mediana de 47 milisegundos con un percentil 95 de 96 es un servidor que parece sano de media y da tirones bajo carga. En un invitado sobresuscrito, esa cifra del percentil 95 y tu steal time suben a la vez, y así es como relacionas el síntoma con la causa. /spark health da el mismo TPS y MSPT junto con la CPU y la memoria en una sola instantánea. (Salida representativa.)

Servidores Source y CS2. El comando de consola stats muestra el uso de CPU y una cifra de fps que sigue al tick rate: un servidor sano de 64 ticks muestra fps iguales o algo superiores a 64, con el tick rate como tope, y cualquier caída bajo carga es un fotograma que la simulación no pudo terminar a tiempo. Ejecútalo varias veces seguidas para ver la varianza, porque una sola línea es solo una instantánea.

La forma más limpia de aislar el coste del hipervisor es mantener todo lo demás constante: la misma CPU, la misma RAM, la misma versión del juego, la misma carga, y cambiar solo si el servidor se ejecuta en bare metal o dentro de un invitado KVM en ese mismo hardware. Es una prueba que conviene hacer en un laboratorio controlado en lugar de discutirla desde los principios.

Lo que esa medición pondría en cifras no es discutible: en hardware idéntico, la ejecución en bare metal mantiene un tiempo de tick del percentil 95 más bajo y más plano, y la desventaja del invitado crece con la carga. Lo que zanja un benchmark es el tamaño de la diferencia en una VM de un solo inquilino que controlas, normalmente pequeña, frente a lo que hace con ella la sobresuscripción, que no lo es.

Los contenedores no son máquinas virtuales

Buena parte de la inquietud sobre si virtualizar desaparece en cuanto separas contenedores y VM, porque no plantean el mismo compromiso. Un contenedor de sistema LXC o un contenedor Docker comparte el kernel del host. No hay kernel invitado, ni hardware virtual, ni capa de planificación de vCPU entre tu proceso y el núcleo. Eso significa que prácticamente no hay steal time ni jitter por virtualización de temporizadores: un servidor de juego en un contenedor sobre bare metal se ejecuta a velocidad prácticamente nativa, con un cgroup que limita cuánta CPU y memoria puede usar. La sobrecarga es un error de redondeo.

Así que «quiero ejecutar varios servidores de juego aislados en una máquina» no exige VM. Los contenedores te dan límites de recursos por servidor, un empaquetado ordenado y rendimiento casi nativo sobre el mismo kernel, que es justo lo que hace por dentro un panel de juegos como Pterodactyl. Los compromisos que sí existen (aislamiento más débil que una VM, kernel compartido, sin migración en caliente) tienen que ver con la seguridad y la operación, no con el rendimiento del tick, y los tratamos a fondo en LXC vs KVM en Proxmox. Para el rendimiento bruto de un servidor de juego, un contenedor en bare metal es la opción casi nativa; la VM es la que añade la capa de planificación de la que trata todo este artículo.

Cuándo una VM es la opción correcta

El enemigo no es la virtualización, es la sobresuscripción. Hay casos reales en los que una VM es la herramienta adecuada, y comparten un rasgo: tú controlas la contención.

  • Servidores de desarrollo, staging y pruebas. La experiencia competitiva de nadie depende del tick p95 de una máquina de staging. Crea VM sin reparos; el aislamiento y la comodidad de los snapshots valen más que los últimos milisegundos.
  • Servidores pequeños o informales. Un servidor de supervivencia para ti y una docena de amigos pasa la mayoría de sus ticks muy por debajo del presupuesto. Hay tanto margen que la sobrecarga del hipervisor nunca se convierte en el cuello de botella, y una VM modesta sirve de sobra.
  • Una VM en tu propio hipervisor. Este es el caso importante. Si alquilas una máquina bare metal entera y ejecutas en ella tu propio hipervisor, decides tú cuántos invitados comparten los núcleos y si están sobresuscritos. Fija la VM del juego a núcleos dedicados, no sobrecomprometas recursos y obtendrás casi toda la flexibilidad de la virtualización con un steal time que controlas tú, no uno que te impone tu proveedor. La diferencia con un VPS barato está únicamente en quién toma la decisión de sobresuscribir.

La configuración que conviene evitar para todo lo que tenga tráfico o sea competitivo es aquella en la que otro tomó esa decisión por ti y le puso un precio agresivo.

Si tienes que virtualizar: ajustes que ayudan

Con una VM en hardware que controlas, unos pocos ajustes recuperan la mayor parte del rendimiento perdido en el peor caso:

  • Fija los vCPU a núcleos físicos. El CPU pinning (vcpupin en libvirt) ata los vCPU de la VM del juego a núcleos físicos concretos, para que el planificador deje de moverlos de un lado a otro. Eso reduce el jitter y mejora el comportamiento de la caché. No compartas esos núcleos fijados con otros invitados.
  • Usa el modelo de CPU del host. Configura el invitado con host-passthrough (o al menos host-model) para que la VM vea la CPU real y su juego de instrucciones completo, en lugar de un modelo de mínimo común denominador que deja rendimiento sobre la mesa.
  • No sobresuscribas los núcleos que importan. Haz coincidir los vCPU de la VM del juego con núcleos reales, y mantén el total de vCPU asignados igual o por debajo de los núcleos físicos cuando importe la estabilidad del tick. La densidad a la que renuncias es la latencia que conservas.
  • Desactiva el ballooning en la VM del juego. Dale una reserva de memoria fija para que el host no pueda recuperar RAM en mitad de una partida. Deja el ballooning para los invitados que lo toleran.
  • Mantén las rutas rápidas de red y disco. Usa virtio con vhost-net y pon el estado del juego en NVMe. La parte de dimensionamiento está en la guía de dimensionamiento de servidores, que también defiende menos núcleos y más rápidos frente a muchos lentos.

Nada de esto hace que una VM supere al bare metal. Cierra la diferencia hasta el punto de que, en una máquina que controlas, deja de importar para la mayoría de los servidores.

El veredicto, según la situación

SituaciónMejor opciónPor qué
Shooter competitivo (CS2 y similares)Bare metalUn presupuesto de tick por debajo de 16 ms no deja sitio al steal ni al jitter
Minecraft público con mucho tráfico o modpack grandeBare metalPresupuesto de tick ajustado con carga de entidades y redstone; manda el p95
SMP pequeño o servidor entre amigosUna VM sirveEl amplio margen de tick absorbe la sobrecarga
Desarrollo, staging o pruebasVM en tu hipervisorLos snapshots y el aislamiento valen más que los últimos milisegundos
Varios servidores en una máquina propiaContenedores en bare metalCasi nativo, límites por servidor, sin capa de vCPU
VM en un hipervisor que es tuyoBien si está ajustadaNúcleos fijados, sin sobrecompromiso; tú controlas la contención
VPS multiinquilino barato y sobrevendidoEvitar para todo lo que tenga tráficoSteal time marcado por vecinos que no ves

La latencia es la otra mitad de que un juego se sienta bien, y depende sobre todo de la geografía y el enrutamiento más que de elegir entre bare metal y VM; la guía de latencia en servidores de juego cubre esa parte.

Desplegar en Serverside.com

Si la carga es competitiva o tiene mucho tráfico, el argumento anterior apunta en una sola dirección: la máquina entera, sin hipervisor entre tu bucle de tick y los núcleos. Un servidor de juego de Serverside.com es bare metal de un solo inquilino en nuestra propia red (AS55285), así que no hay steal time, ni vecinos ruidosos, ni una sobresuscripción que decida nadie más que tú. El aprovisionamiento tarda menos de un minuto, y una mitigación DDoS siempre activa protege la interfaz pública, algo que para un servidor de juego no es opcional. Si prefieres dividir tú mismo una máquina en VM, también puedes: alquila el hardware dedicado, ejecuta tu propio hipervisor y todas las decisiones de contención que este artículo te ha dicho que vigiles quedan en tus manos.

Preguntas frecuentes

¿Una VM siempre añade lag a un servidor de juego?

No. Una VM en hardware que controlas, con los vCPU fijados y sin sobresuscripción, añade una sobrecarga tan pequeña que la mayoría de los servidores nunca la notan. El lag que se atribuye a la «virtualización» casi siempre viene de la sobresuscripción y no del hipervisor en sí: un VPS compartido en el que tu tiempo de CPU depende de la carga de otros inquilinos. El mecanismo de fondo es el steal time de CPU, y puedes medirlo directamente.

¿Qué es el steal time de CPU y a partir de qué valor es malo?

El steal time (%st en top) es el porcentaje de tiempo en que tu CPU virtual estaba lista para ejecutarse pero tuvo que esperar a que el host le asignara un núcleo físico. En bare metal siempre es cero. En una VM sana se queda cerca de cero. Una regla práctica habitual dice que un steal sostenido por encima del 10 por ciento significa que el invitado va más lento de lo que debería, y en un servidor de juego de tick fijo basta con unos pocos puntos para que aparezcan ticks lentos.

¿Por qué mi servidor de juego en un VPS va con lag si el uso de CPU parece bajo?

Porque el uso de CPU dentro del invitado no muestra la contención en el host. Tu servidor puede estar al 30 por ciento de CPU y aun así perder ticks si el host hace esperar una y otra vez a tu CPU virtual; ese tiempo perdido aparece como steal, no como uso. Mira la columna st en top o en vmstat 1. Un steal alto con un uso bajo es la firma clásica de un VPS sobresuscrito.

¿Son mejores los contenedores que las VM para el rendimiento de un servidor de juego?

En rendimiento bruto, sí. Un contenedor Docker o LXC en bare metal comparte el kernel del host, así que no hay capa de planificación de CPU virtuales ni steal time, y se ejecuta a velocidad casi nativa. Las VM ofrecen un aislamiento más fuerte y funciones como la migración en caliente que los contenedores no tienen. Para el rendimiento del tick, un contenedor en bare metal supera a una VM; para aislar inquilinos no fiables, gana la VM. Nuestra comparativa LXC vs KVM recoge el compromiso completo.

¿Cómo sé si la virtualización está perjudicando a mi servidor?

Con dos cifras. Para el steal time, ejecuta top, vmstat 1 o mpstat -P ALL 1 y lee la columna st o %steal. Para la salud del tick en Minecraft, instala el profiler spark y ejecuta /spark tps, fijándote en el MSPT del percentil 95 y no en la media. En servidores Source y CS2, el comando stats muestra una cifra de fps que sigue al tick rate. Si el steal time y el tiempo de tick del percentil 95 suben a la vez, el problema es el host.

Clay Berndt

Escrito por

Clay Berndt

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.