Automatizando o XNA Performance Testing?

8

Fiquei me perguntando o que as pessoas abordam ou pensam sobre como automatizar o teste de desempenho no XNA. Atualmente, estou olhando apenas para trabalhar em 2D, mas isso representa muitas áreas em que o desempenho pode ser aprimorado com diferentes implementações.

Um exemplo seria se você tivesse duas implementações diferentes de particionamento espacial, uma pode ser mais rápida que a outra, mas sem fazer alguns testes de desempenho reais, você não seria capaz de dizer qual deles com certeza (a menos que visse que o código estava descaradamente lento em certos peças). Você pode escrever um teste de unidade que, por um determinado período, continue adicionando / atualizando / removendo entidades para ambas as implementações e veja quantas foram feitas em cada período de tempo e quanto maior, mais rápido será o mais rápido (neste exemplo).

Outro exemplo de nível superior seria se você quisesse ver quantas entidades você pode ter na tela aproximadamente sem ficar abaixo de 60fps. O problema disso é que, para automatizá-lo, você precisará usar o truque de forma oculta ou alguma outra coisa para iniciar um jogo falso e testar puramente quais partes são importantes e desativar todo o resto.

Sei que esse não é um caso simples, realmente, mesmo que você possa automatizar os testes; realmente depende de um ser humano interpretar se os resultados têm desempenho suficiente, mas, como parte de uma etapa de construção, você pode executar esses testes e publicar os resultados em algum lugar para comparação.

Dessa forma, se você for da versão 1.1 para 1.2, mas alterou alguns algoritmos subjacentes, poderá perceber que geralmente a pontuação de desempenho teria aumentado, o que significa que você melhorou o desempenho geral do aplicativo e, em seguida, de 1.2 para 1.3, pode perceber que você diminuiu um pouco o desempenho geral.

Então, alguém automatizou esse tipo de coisa em seus projetos? Em caso afirmativo, como você mede suas comparações de desempenho em alto nível e quais estruturas você usa para testar? Ao fornecer o código que você escreveu para que seja testável / ridicularizado na maioria das partes, você pode apenas usar seus testes como um mecanismo para obter alguns resultados de desempenho ...

=== Editar ===

Apenas para maior clareza, estou mais interessado na melhor maneira de usar testes automatizados no XNA para rastrear seu desempenho, não para testar ou adivinhar executando manualmente o jogo em uma máquina. Isso é completamente diferente de ver se o seu jogo pode ser jogado no hardware X, é mais sobre acompanhar a mudança no desempenho à medida que o mecanismo / estrutura do jogo muda.

Conforme mencionado em um dos comentários, você pode testar facilmente "quantos nós posso inserir / remover / atualizar dentro do QuadTreeA em 2 segundos", mas você deve examinar fisicamente esses resultados sempre para ver se foram alterados, o que pode ser bem e ainda é melhor do que apenas jogar, para ver se você percebe alguma diferença entre as versões. No entanto, se você colocar uma declaração para notificá-lo de uma falha, se ela for menor do que, digamos, 5000 em 2 segundos, você terá um teste quebradiço, pois é contextual ao hardware, não apenas à implementação. Embora isso seja dito, esse tipo de teste automatizado é realmente útil se você estiver executando seus testes como algum tipo de pipeline de criação, ou seja:

Caixa -> Executar testes de unidade -> Executar testes de integração -> Executar testes de desempenho -> Pacote

Portanto, você pode comparar facilmente as estatísticas de uma construção para outra no servidor de IC como um relatório de algum tipo e, novamente, isso pode não significar muito para ninguém, se você não estiver acostumado à Integração Contínua. O principal ponto crucial dessa questão é ver como as pessoas gerenciam isso entre compilações e como elas acham melhor informar sobre elas. Como eu disse, pode ser subjetivo, mas como o conhecimento será obtido com as respostas, parece uma pergunta que vale a pena.

Grofit
fonte
+1 ótima pergunta. Ainda não fiz isso, mas preciso fazê-lo em breve.
precisa saber é o seguinte
Só para esclarecer, não estou falando realmente de profilers ou ferramentas externas, embora isso possa ser algo adicional para ajudar a diagnosticar seções lentas etc. O que estou pensando é mais sobre o uso de seus testes de unidade para fornecer algum contexto sobre se você também está melhorando o desempenho, para poder implementar um novo algoritmo para busca de caminhos e testá-lo imediatamente isoladamente em relação à sua versão anterior, e comparar os números instantaneamente dizendo que você o aprimorou ou perdeu seu tempo sem precisar integrá-lo no projeto principal e implantá-lo.
Grofit 18/01/12
sua pergunta parece um pouco confusa; você está falando sobre medição de desempenho geral, que pode ser feita SEM testes; mas você também pode escrever testes como "o teste X acontece em menos de 3 segundos".
precisa saber é o seguinte
Sim, e esse "teste X acontece em menos de 3 segundos" está no caminho certo, mas, em vez disso, um teste como "Quantos nós posso inserir em uma árvore quádrupla em 5 segundos", o resultado disso para uma construção pode ser 10000 e a próxima compilação pode ser 5000. Ao ver isso imediatamente, você pode tomar uma decisão informada se tiver apresentado um problema. O problema para mim é que todas essas informações são boas, mas você precisa examiná-las. Como adicionar uma declaração para <7500 no período pode parecer bom, mas se você executá-la em uma máquina diferente, ela pode não passar, mas, na realidade, a IMPLEMENTATION não é mais lenta.
Grofit 18/01/12

Respostas:

2

Suponho que você queira descartar completamente "Executar o jogo real", então basicamente minha resposta é desqualificada desde o início. Mas talvez você possa tirar algo disso, por isso eu posto isso independentemente:

Para minha tese de mestrado, tenho várias implementações independentes / paralelas para obter o mesmo em alguns módulos do mecanismo de jogo e preciso realizar algumas medições de desempenho. Tecnicamente, nada me impediria de executar o jogo e olhar para os números exibidos no criador de perfil na tela, mas eu ainda queria automatizar isso porque é um processo tedioso de executar sempre que minha implementação é alterada.

Então, o que eu tenho é o seguinte:

  • Um criador de perfil com escopo (que coloca um objeto na pilha, leva um carimbo de data e hora na construção e outro na desconstrução) usado para medir quanto tempo a função / escopo de interesse levou para executar
  • Um módulo que armazena um certo número de amostras com perfil e despeja a média entre as últimas n amostras em um arquivo de texto simples
  • Uma linha de comando no jogo que pode ser usada para iniciar um jogo, carregar um mapa, alterar o algoritmo usado dentro do módulo a ser inspecionado, alterar o caminho do arquivo de despejo do criador de perfil e muitas outras coisas. A linha de comando é configurada para verificar um determinado arquivo especial no diretório executável e carregá-lo para executar a cadeia de caracteres recuperada (como um meio de comunicação entre processos muito, muito grosseira)

Então, o que isso me permite fazer é iniciar meu aplicativo a partir de qualquer ambiente de script meio decente (por exemplo, prompt de comando do Windows por meio de scripts em lote - mas na verdade eu uso o Ruby para esse fim), definir um caminho de arquivo de despejo, carregar um mapa e deixá-lo executando por alguns minutos, encerre o jogo em execução, defina outro caminho do arquivo de despejo, mude o algoritmo para usar, carregue o mapa novamente, enxágue, repita. O script Ruby se comunica com o jogo em andamento, criando esse arquivo especial que o módulo de linha de comando está procurando e colocando os comandos desejados na sintaxe que a linha de comando entende nele.

Na verdade, não tenho integração contínua neste projeto no momento, mas nada me impediria de aprimorar esse script Ruby para também analisar os logs de desempenho gerados e produzir XML compatível com xUnit para se comunicar com o sistema de CI quando o desempenho tiver inesperadamente por algum motivo e execute o script em todas as compilações completas no servidor de compilação.

Tudo bem, então meu jogo também não é escrito em XNA (é simples em C ++ e DirectX), nem essa abordagem respeita o fato de que você realmente não deseja executar o jogo em seu servidor de build. Ele também não é nem de longe tão flexível quanto o que você provavelmente deseja - mas, ainda assim, é uma abordagem simples e de baixa tecnologia para a medição automatizada de desempenho que é um pouco favorável ao CI (desde que um servidor de construção robusto seja).

Edit: Quanto ao quão longe eu realmente levei essa abordagem - só comparo as medições de desempenho obtidas em diferentes implementações deste módulo. Mas todo o sistema é configurado de uma maneira que me permita despejar qualquer uma das categorias definidas para minha estrutura de criação de perfil leve e usar o ambiente de script externo para interpretar os resultados da maneira que parecer útil aqui e ali. Tirando o aspecto do perfil de desempenho da equação, pretendo ainda

  • Verifique a validade / consistência de todos os ativos carregando todos os mapas que contêm todos os modelos / texturas / sons e verificando os logs do mecanismo quanto a algo incomum
  • faça um teste de estresse ao mecanismo e monitore os logs quanto a comportamentos inesperados em um período de várias horas / dias
Koarl
fonte
11
Todas as boas informações deram a você um +1. Pelo que parece, tudo o que você está fazendo acima pode ser facilmente feito em um tipo de teste de integração. A única coisa que você precisa se preocupar é zombar do jogo / simulação real. Como você está no processo de isolar os componentes de seus mecanismos / estruturas para que possam ser testados em seu próprio contexto, é nesse ponto que estou tentando chegar. Como não estou querendo testar o desempenho do meu jogo, por ser uma fera em constante mudança, o quadro raramente muda e pode ser facilmente configurado para executar uma determinada quantidade de cenários, como você mencionou.
Grofit 19/03/12
Obrigado. Conforme apontado pelas coisas que quero alcançar no futuro, pretendi automatizar coisas que acontecem no jogo real - o resultado também foi bastante conveniente para as medições de desempenho.
21412 Koarl
0

Não vejo o que você descreve como uma ferramenta útil. Como desenvolvedor, um número simples de desempenho é quase inútil.

O que você deseja é criar um perfil do seu código, dividi-lo em partes lógicas e medir quanto tempo cada um deles usa, pico e média. Agora você pode dizer qual parte do código está causando problemas e sabe onde procurar otimizações.

A parte complicada não são as alterações de desempenho de uma construção para a outra, você não precisa de um automatizado para descobrir isso. A parte complicada são as diferenças de desempenho entre máquinas diferentes, não há como extrapolar o desempenho de uma máquina para outra com uma placa de vídeo diferente etc.

Então, o que você quer é um recurso de referência para que você possa executar um clique e obter os números de criação de perfil. Dessa forma, você poderá testar várias máquinas simultaneamente. Existem várias maneiras de fazer isso, por exemplo, você pode substituir a entrada do usuário para chegar o mais próximo possível da execução de uma sessão normal do jogo.

Você também pode querer fazer um teste mais longo para detectar vazamentos de memória.

aaaaaaaaaaaa
fonte
3
Se você seguir uma abordagem típica de estilo de IC, em que executa o software por meio de um servidor de compilação, sempre estará testando na mesma máquina e sempre com o mesmo hardware, o que fornece uma linha de base para seus números. Como essa era a direção de onde eu estava vindo realmente. Você diz que não precisa de uma ferramenta para descobrir as mudanças de desempenho entre as compilações, o que é verdade. Você pode executá-lo e ver a diferença, mas seria ótimo se o sistema de compilação ou o computador atual pudesse fornecer esses números sem que você tenha para fazer algo diferente de executar um teste.
Grofit 18/01/12
Se você é um pouco sério sobre o teste, precisa de várias máquinas de teste diferentes. De qualquer forma, qual é o problema real? Você não tem certeza de como codificar uma referência no jogo?
Aaaaaaaaaaaa
Não há problema, como tal, estou apenas tentando obter algumas informações sobre como algumas pessoas aplicaram isso em seus projetos. Não acho que ter máquinas separadas ajude de forma alguma, pois você não está realmente testando para ver se é executado a 30fps em hardware baixo e 60fps em hardware rápido. Você está retirando o hardware da equação e olhando puramente para o seu mecanismo / código-fonte. Na verdade, não importa se você está testando em um 486 ou quad core, pois está testando uma construção contra outra, e não um conjunto de hardware novamente em outro.
Grofit 18/01/12
3
Eu tenho que concordar um pouco com Grofit e eBusiness neste. Os testes automatizados são importantes, especialmente em projetos grandes, para que, quando qualquer construção for concluída, você saberá se algo prejudicou ou ajudou no desempenho, e isso é idealmente feito em uma máquina. Com os jogos para PC, pelo menos, você também precisa testar diversas variedades de hardware, seus testes automatizados podem dizer que o desempenho é ótimo, mas você executa seu jogo em uma GPU antiga ou se vê na memória virtual e, de repente, em seus tanques de desempenho. Você precisa testar essas coisas antes que elas cheguem às mãos dos clientes.
Nic Foster
@ Grofit O problema é que pode ser apenas a máquina antiga que quebra a compilação. Não é incomum que uma mudança não tenha um efeito significativo no desempenho de um computador novo ou seja uma melhoria, enquanto a mesma mudança impede completamente que o jogo seja executado em um computador antigo. Você não pode tirar o hardware da equação, não existe desempenho de código isolado. Mas se você deseja configurar um teste automatizado em apenas uma máquina, pelo menos faça isso em junker antigo, que lhe dará uma chance muito maior de que o teste falhe.
Aaaaaaaaaaaa