Desempenho do servidor FPS para vários jogadores

12

Isso está relacionado ao desempenho do MMO, exceto que a pergunta é sobre largura de banda. Isso é sobre a carga da CPU.

Eu montei um FPS simples usando node.js e webGL. É extremamente simples, muito parecido com o clone BuddyMaze do MIDI Maze. Há muito pouco, todo mundo se move em duas dimensões (sem altura), dispara projéteis simples e se choca contra paredes.

No momento, se eu fizer várias conexões com o servidor em que todos os jogadores disparam rapidamente enquanto gira em círculos, posso receber de 15 a 20 jogadores no jogo antes que o servidor atinja o núcleo e diminua a velocidade. E isso é quando rodando a 30 qps no servidor. A 10 qps, recebo cerca de 25 a 30 conexões. Isso é muito ruim, já que o jogo terá muito mais a fazer em breve e eu precisarei ajustar mais jogadores para que isso seja um empreendimento possível.

Meu irmão apenas apontou algumas estatísticas sobre o servidor TF2 de seu colega de trabalho. O servidor dele tem especificações mais baixas que o nosso, mas roda o TF2, obviamente um jogo muito mais complexo, com impressionantes 500 ticks por segundo, com 36 usuários por núcleo. Além disso, atualmente consumimos muito mais largura de banda do que eles, mas ainda não tentamos diminuir isso.

Como isso é possível? Que tipo de truques existem para aumentar o desempenho do servidor nessa magnitude? Algumas coisas que eu sei incluem:

  • Diminuindo a taxa de quadros no servidor e interpolando posições no cliente. Consegui alguns benefícios, mas claramente o servidor TF2 nem se preocupa com isso.
  • Fazer coisas caras, como detecção de colisão no cliente e verificá-la com pouca frequência no servidor. Ainda não mudei isso, vou mudar esta noite. Mesmo assim, não espero um ganho tão grande.
  • Divida o campo em regiões (quad árvores) para minimizar os cálculos. Ainda não tive uma oportunidade para isso.
  • Eu considerei a infeliz possibilidade de que o node.js seja muito mais lento do que o TF2 está usando e pode não ser adequado para esse tipo de tarefa de alta intensidade.
  • Está tudo na mágica da configuração do servidor?

Então, quais são os outros truques da indústria para fazer apenas o mínimo necessário no servidor, mas ainda assim ter uma experiência de jogo impecável? Há um grande conflito entre "adiar para o cliente economizar tempo na CPU" e "não confiar no cliente"; talvez seja útil saber onde a linha é traçada em várias situações?

Atualizar

Realizar perfis é realmente o único mantra que eu já achei absolutamente infalível. Eu rapidamente agrupei algumas funções de temporização no código (obrigado, FP!) E descobri o que eu nunca esperava: o ato de transmitir os dados para os clientes é responsável por quase todo o tempo de execução. Especificamente, cerca de 90% dela. Testes adicionais mostraram que esse tempo depende do número de clientes e do tamanho dos dados, mas mais ainda do último. Em uma carga de 20 usuários, reduzi meu tempo de transmissão em 90%, de 24ms para pouco mais de 2ms, enviando apenas "{}" em vez dos dados completos. Mas com apenas 5 usuários, a transmissão leva cerca de 0,5 ms. Então, eu claramente preciso fazer alguma otimização aqui.

A primeira melhoria mais óbvia é a verificação da linha de visão. Isso diminuiria o número de pessoas que se preocupam com os dados e também a quantidade de dados enviados às partes interessadas. Existem outros truques neste domínio que posso tentar, que se concentram em minimizar o custo da minha operação de transmissão?

Tesserex
fonte
5
Perfil do código é realmente tudo o que eu poderia sugerir. Meu palpite é que não está tão afinado quanto você pensa e é por isso que o TF2 está executando uma taxa de tick mais alta em menos hardware. Eu também acho que o TF2 pode estar fazendo todas as coisas que você sugeriu e, como resultado, está contribuindo para o desempenho mais alto.
Nate
1
Estou interessado em ouvir seus resultados mais recentes, você conseguiu um melhor desempenho do node.js?
Iddqd 4/10/11

Respostas:

5

Seu servidor não deve enviar o estado de todos os jogadores a todos os jogadores a cada tick. Em vez disso, ele deve enviar uma mensagem especialmente criada para cada cliente, dizendo a cada 500 ms dizendo "esses x players na sua porta de visualização devem estar nessas coordenadas em 500 ms". Na maioria das vezes, isso funciona bem, mas se o servidor perceber que forneceu informações incorretas, apenas enviará uma mensagem extra.

Isso diminuirá drasticamente o tráfego da rede.

Outra coisa a considerar é não ter ticks de jogo no servidor, mas fazer com que o cliente envie mensagens somente quando uma ação ocorrer (mudança de direção, tiro disparado) e depois calcule com antecedência no servidor quando uma ação for recebida.

sorenbs
fonte
Sim, estou adicionando verificação de linha de visão agora. Na verdade, os ganhos foram mínimos, de 45 ms para 25 jogadores, até 35 ms. Mas pode haver alguma sobrecarga extra para o uso de comandos de envio individuais em vez da transmissão. E só envio mensagens na entrada. Mas você está certo, pode haver uma maneira de não precisar marcar, apenas quando a entrada é recebida.
Tesserex
1

Eu considerei a infeliz possibilidade de que o node.js seja bem mais lento do que o TF2 está usando e pode não ser adequado para esse tipo de tarefa de alta intensidade.

Provavelmente é isso. O servidor do TF2 é escrito usando C / C ++ e, portanto, será mais rápido que o node.js (que, se bem me lembro, usa Javascript interpretado em Java)

O Quake baseado no WebGL do Google usa java para o servidor, e o código fonte é encontrado aqui: http://code.google.com/p/quake2-gwt-port/ . Pode valer a pena examinar isso para ver como é feito. Também me pergunto o que você quer dizer quando fala em ter uma taxa de quadros no servidor. Não há motivo para renderizar nada no servidor, ele deve estar lá apenas para processar comandos enviados pelo cliente.

Por fim, a regra "não confie no cliente" é mais importante do que transferir cálculos caros para o cliente na esperança de melhorar o desempenho. Especialmente algo tão importante quanto a detecção de colisões. Duplamente quando o seu jogo é baseado em Javascript e, portanto, bastante fácil de hackear (comparado a algo como o TF2 que é compilado).

Sei que isso não é uma resposta muito grande, mas espero que ele o indique em algumas direções que podem ajudar a melhorar o desempenho.

thedaian
fonte
7
Eu deveria ter dito a taxa de tick em vez da taxa de quadros. Claro que nada é processado no servidor. Quero dizer o intervalo em que ele processa os comandos no loop do jogo. Além disso, algumas respostas sugerem que você pode fornecer coisas como detecção de colisão ao cliente, desde que faça verificações aleatórias a cada poucos segundos. Alguém disse que elimina os trapaceiros rapidamente.
Tesserex