Rendimiento del lado del servidor FPS multijugador

12

Esto está relacionado con el rendimiento de MMO, excepto que la pregunta es sobre el ancho de banda. Esto se trata de la carga de la CPU.

Creé un FPS simple usando node.js y webGL. Es extremadamente simple, muy parecido al clon BuddyMaze de MIDI Maze. Están sucediendo muy pocas cosas, todos se mueven en dos dimensiones (sin altura), disparan proyectiles simples y se topan con paredes.

En este momento, si hago múltiples conexiones al servidor donde cada jugador dispara rápidamente mientras gira en círculos, puedo obtener alrededor de 15-20 jugadores en el juego antes de que el servidor maximice un núcleo y disminuya la velocidad. Y esto es cuando se ejecuta a 30 fps en el servidor. A 10 fps, obtengo unas 25-30 conexiones. Esto es bastante malo, ya que el juego tendrá mucho más que hacer pronto y tendré que adaptar a más jugadores para que esto sea un esfuerzo factible.

Mi hermano acaba de señalar algunas estadísticas sobre el servidor TF2 de su compañero de trabajo. Su servidor tiene especificaciones más bajas que las nuestras, pero ejecuta TF2, obviamente un juego mucho más complejo, a la friolera de 500 tics por segundo, con 36 usuarios por núcleo. Además, actualmente consumimos mucho más ancho de banda que ellos, pero aún no hemos tratado de reducirlo.

¿Cómo es esto posible? ¿Qué tipo de trucos existen para aumentar el rendimiento del servidor a esta magnitud? Algunas cosas que sé incluyen:

  • Disminuir la velocidad de fotogramas en el servidor e interpolar posiciones en el cliente. Obtuve algunos beneficios, pero claramente el servidor TF2 ni siquiera se molesta con esto.
  • Hacer cosas costosas como la detección de colisiones en el cliente y verificarlo con poca frecuencia en el servidor. Todavía no he movido esto, lo haré esta noche. Aun así, no espero una ganancia tan enorme.
  • Divide el campo de juego en regiones (árboles cuádruples) para minimizar los cálculos. No he tenido una oportunidad para esto todavía.
  • He considerado la desafortunada posibilidad de que node.js sea mucho más lento que lo que sea que esté usando TF2, y puede que no sea adecuado para este tipo de tarea de alta intensidad.
  • ¿Está todo en la configuración del servidor mágico?

Entonces, ¿cuáles son los otros trucos de la industria para hacer solo el mínimo requerido en el servidor pero aún así tener una experiencia de juego perfecta? Existe un gran conflicto entre "diferir al cliente para ahorrar tiempo de la CPU" y "no confiar en el cliente", por lo que tal vez sea útil saber dónde se traza la línea en varias situaciones.

Actualizar

Perfilar realmente es el único mantra que he encontrado que es absolutamente infalible. Rápidamente envolví algunas funciones de temporización alrededor de mi código (¡gracias, FP!) Y descubrí lo que nunca esperé: el acto de transmitir los datos a los clientes representa casi todo el tiempo de ejecución. Específicamente, alrededor del 90% de la misma. Pruebas posteriores mostraron que este tiempo depende tanto del número de clientes como del tamaño de los datos, pero más aún de este último. Con una carga de 20 usuarios, reduje mi tiempo de transmisión en un 90%, de 24 ms a poco más de 2 ms, enviando solo "{}" en lugar de los datos completos. Pero con solo 5 usuarios, la transmisión tarda alrededor de 0,5 ms. Entonces claramente necesito hacer alguna optimización aquí.

La primera mejora más obvia es la verificación de la línea de visión. Esto disminuiría tanto el número de personas que se preocupan por los datos, como también la cantidad de datos enviados a las partes interesadas. ¿Hay otros trucos en este ámbito que pueda probar, que se centren en minimizar el costo de mi operación de transmisión?

Tesserex
fuente
55
Perfil del código es realmente todo lo que podría sugerir. Supongo que no está tan bien ajustado como crees y es por eso que TF2 está ejecutando una tasa de tick más alta en menos hardware. También creo que TF2 puede estar haciendo todas las cosas que sugirió hacer y, como resultado, está contribuyendo a que su rendimiento sea más alto.
Nate
1
Estoy interesado en escuchar sus últimos resultados, ¿pudo obtener un mejor rendimiento de node.js?
iddqd

Respuestas:

5

Su servidor no debe enviar el estado de todos los jugadores a todos los jugadores en cada tic. En su lugar, debe enviar un mensaje especialmente diseñado a cada cliente que diga cada 500 ms diciendo "estos x jugadores en su puerto de visualización deben estar en estas coordenadas en 500 ms". La mayoría de las veces esto funcionará bien, pero si el servidor se da cuenta de que ha proporcionado información incorrecta, solo envía un mensaje adicional.

Esto disminuirá dramáticamente el tráfico de red.

Otra cosa a considerar es no tener ticks de juego en el servidor, sino que el cliente envíe mensajes solo cuando ocurra una acción (cambio de dirección, disparo) y luego calcular con anticipación en el servidor cuando se recibe una acción.

sorenbs
fuente
Sí, estoy agregando comprobación de línea de visión en este momento. En realidad, las ganancias fueron mínimas, desde 45 ms para 25 jugadores, hasta 35 ms. Pero puede haber una sobrecarga adicional por usar comandos de envío individuales en lugar de difusión. Y solo envío mensajes en la entrada. Pero tiene razón, puede haber una manera de no tener que marcar nada, solo cuando se recibe una entrada.
Tesserex
1

He considerado la desafortunada posibilidad de que node.js sea mucho más lento que lo que sea que esté usando TF2, y puede que no sea adecuado para este tipo de tarea de alta intensidad.

Probablemente sea esto. El servidor de TF2 está escrito usando C / C ++, y por lo tanto, será más rápido que node.js (que si no recuerdo mal, usa Javascript interpretado en Java)

Quake, basado en WebGL de Google, usa Java para el servidor, y el código fuente se encuentra aquí: http://code.google.com/p/quake2-gwt-port/ . Podría valer la pena revisar eso para ver cómo se hace. También me pregunto a qué te refieres cuando hablas de tener un framerate en el servidor. No hay ninguna razón para representar nada en el servidor, solo debe estar allí para procesar los comandos enviados por el cliente.

Finalmente, la regla "no confíe en el cliente" es más importante que descargar cálculos costosos en el cliente con la esperanza de mejorar el rendimiento. Especialmente algo tan importante como la detección de colisiones. Doblemente cuando tu juego está basado en Javascript, y por lo tanto es bastante fácil de hackear (en comparación con algo como TF2 que se compila).

Sé que esto no es una gran respuesta, pero espero que te indique algunas direcciones que podrían ayudar a mejorar el rendimiento.

thedaian
fuente
77
Debería haber dicho tasa de tick en lugar de velocidad de fotogramas. Por supuesto, no se muestra nada en el servidor. Me refiero al intervalo en el que procesa los comandos en el bucle del juego. Además, algunas respuestas sugieren que puede proporcionar cosas como la detección de colisiones al cliente, siempre que realice verificaciones aleatorias cada pocos segundos. Alguien dijo que elimina a los tramposos bastante rápido.
Tesserex