Share via


Consultas de desempenho do lado do servidor

Um bom desempenho de renderização no servidor é fundamental para taxas de quadros estáveis e uma boa experiência do usuário. É importante monitorar as características de desempenho no servidor cuidadosamente e otimizar quando necessário. Os dados de desempenho podem ser consultados por meio de funções de API dedicadas.

O mais impactante para o desempenho de renderização são os dados de entrada do modelo. Você pode ajustar os dados de entrada conforme descrito em Configurando a conversão de modelo.

O desempenho do aplicativo do lado do cliente também pode ser um gargalo. Para uma análise aprofundada do desempenho do lado do cliente, recomenda-se fazer um performance trace.

Linha do tempo cliente/servidor

Antes de entrar em detalhes sobre os vários valores de latência, vale a pena dar uma olhada nos pontos de sincronização entre cliente e servidor na linha do tempo:

Pipeline timeline

A ilustração mostra como:

  • uma estimativa de Pose é iniciada pelo cliente a uma taxa de quadros constante de 60 Hz (a cada 16,6 ms)
  • Em seguida, o servidor inicia a renderização, com base na pose
  • O servidor envia de volta a imagem de vídeo codificada
  • o cliente decodifica a imagem, executa algum trabalho de CPU e GPU em cima dela e, em seguida, exibe a imagem

Consultas de estatísticas de quadros

As estatísticas de quadro fornecem algumas informações de alto nível para o último quadro, como latência. Os dados fornecidos na FrameStatistics estrutura são medidos no lado do cliente, portanto, a API é uma chamada síncrona:

void QueryFrameData(RenderingSession session)
{
    FrameStatistics frameStatistics;
    if (session.GraphicsBinding.GetLastFrameStatistics(out frameStatistics) == Result.Success)
    {
        // do something with the result
    }
}
void QueryFrameData(ApiHandle<RenderingSession> session)
{
    FrameStatistics frameStatistics;
    if (session->GetGraphicsBinding()->GetLastFrameStatistics(&frameStatistics) == Result::Success)
    {
        // do something with the result
    }
}

O objeto recuperado FrameStatistics contém os seguintes membros:

Membro Explicação
LatencyPoseToReceive Latência da estimativa de pose da câmera no dispositivo cliente até que um quadro de servidor para essa pose esteja totalmente disponível para o aplicativo cliente. Esse valor inclui ida e volta da rede, tempo de renderização do servidor, decodificação de vídeo e compensação de desvios. Ver intervalo 1 na ilustração acima.
LatencyReceiveToPresent Latência desde a disponibilidade de um quadro remoto recebido até que o aplicativo cliente chame PresentFrame na CPU. Ver intervalo 2 na ilustração acima.
LatencyPresentToDisplay Latência desde a apresentação de um quadro na CPU até o visor acender. Esse valor inclui o tempo da GPU do cliente, qualquer buffer de quadros executado pelo sistema operacional, reprojeção de hardware e tempo de varredura de exibição dependente do dispositivo. Ver intervalo 3 na ilustração acima.
TimeSinceLastPresent O tempo entre as chamadas subsequentes para PresentFrame na CPU. Valores maiores do que a duração da exibição (por exemplo, 16,6 ms em um dispositivo cliente de 60 Hz) indicam problemas causados pelo aplicativo cliente não terminar sua carga de trabalho da CPU a tempo.
VideoFramesRecebidos O número de quadros recebidos do servidor no último segundo.
VideoFrameReusedCount Número de quadros recebidos no último segundo que foram usados no dispositivo mais de uma vez. Valores diferentes de zero indicam que os quadros tiveram que ser reutilizados e reprojetados devido a desvios de rede ou tempo excessivo de renderização do servidor.
VideoFramesIgnorado Número de quadros recebidos no último segundo que foram decodificados, mas não mostrados na exibição porque um quadro mais recente chegou. Valores diferentes de zero indicam que o nervosismo da rede fez com que vários quadros fossem atrasados e, em seguida, chegassem juntos ao dispositivo cliente em um burst.
VideoFramesDescartado Muito semelhante ao VideoFramesSkipped, mas a razão para ser descartado é que um quadro chegou tão tarde que não pode mais ser correlacionado com qualquer pose pendente. Se esse descarte acontecer, haverá uma grave contenção de rede.
VideoFrameMinDelta Quantidade mínima de tempo entre dois quadros consecutivos chegando durante o último segundo. Juntamente com VideoFrameMaxDelta, esta gama dá uma indicação de desvios causados pela rede ou codec de vídeo.
VideoFrameMaxDelta Quantidade máxima de tempo entre dois quadros consecutivos chegando durante o último segundo. Juntamente com VideoFrameMinDelta, este intervalo dá uma indicação de desvios causados pela rede ou codec de vídeo.

A soma de todos os valores de latência é normalmente muito maior do que o tempo de quadro disponível em 60 Hz. Isso é OK, porque vários quadros estão em vôo em paralelo e novas solicitações de quadros são iniciadas na taxa de quadros desejada, conforme mostrado na ilustração. No entanto, se a latência se tornar muito grande, isso afeta a qualidade da reprojeção do estágio tardio e pode comprometer a experiência geral.

VideoFramesReceived, VideoFrameReusedCounte pode ser usado para avaliar o desempenho da rede e VideoFramesDiscarded do servidor. Uma combinação de um valor baixo VideoFramesReceived e um valor alto VideoFrameReusedCount pode indicar congestionamento da rede ou baixo desempenho do servidor. Um valor alto VideoFramesDiscarded também indica congestionamento da rede.

Por fim,TimeSinceLastPresentVideoFrameMinDelta e VideoFrameMaxDelta dê uma ideia da variação de quadros de vídeo recebidos e chamadas locais presentes. Alta variância significa taxa de quadros instável.

Nenhum dos valores acima dá uma indicação clara de latência de rede pura (as setas vermelhas na ilustração), porque o tempo exato em que o servidor está ocupado renderizando precisa ser subtraído do valor LatencyPoseToReceivede ida e volta. A parte do lado do servidor da latência geral são informações que não estão disponíveis para o cliente. No entanto, o próximo parágrafo explica como esse valor é aproximado através da entrada extra do servidor e exposto através do NetworkLatency valor.

Consultas de avaliação de desempenho

As consultas de avaliação de desempenho fornecem informações mais detalhadas sobre a carga de trabalho da CPU e GPU no servidor. Como os dados são solicitados do servidor, consultar um instantâneo de desempenho segue o padrão assíncrono usual:

async void QueryPerformanceAssessment(RenderingSession session)
{
    try
    {
        PerformanceAssessment result = await session.Connection.QueryServerPerformanceAssessmentAsync();
        // do something with result...
    }
    catch (RRException ex)
    {
    }
}
void QueryPerformanceAssessment(ApiHandle<RenderingSession> session)
{
    session->Connection()->QueryServerPerformanceAssessmentAsync([](Status status, PerformanceAssessment result) {
        if (status == Status::OK)
        {
            // do something with result...
        }
    });
}

Ao contrário do objeto, o objeto contém informações do lado do FrameStatisticsPerformanceAssessment servidor:

Membro Explicação
TimeCPU Tempo médio de CPU do servidor por quadro em milissegundos
TimeGPU Tempo médio da GPU do servidor por quadro em milissegundos
UtilizaçãoCPU Utilização total da CPU do servidor em percentagem
UtilizaçãoGPU Utilização total da GPU do servidor em percentagem
MemóriaCPU Utilização total da memória principal do servidor em percentagem
MemóriaGPU Utilização total de memória de vídeo dedicada em percentagem da GPU do servidor
Latência de rede A latência média aproximada da rede de ida e volta em milissegundos. Na ilustração acima, este valor corresponde à soma das setas vermelhas. O valor é calculado subtraindo o tempo de renderização real do servidor do LatencyPoseToReceive valor de FrameStatistics. Embora essa aproximação não seja precisa, ela dá alguma indicação da latência da rede, isolada dos valores de latência calculados no cliente.
PolígonosRenderizados O número de triângulos renderizados em um quadro. Esse número também inclui os triângulos que são abatidos posteriormente durante a renderização. Isso significa que esse número não varia muito entre as diferentes posições da câmera, mas o desempenho pode variar drasticamente, dependendo da taxa de abate do triângulo.
PontosRenderizados O número de pontos em nuvens de pontos renderizados em um quadro. Aplicam-se aqui os mesmos critérios de abate acima PolygonsRendered referidos.

Para ajudá-lo a avaliar os valores, cada porção vem com uma classificação de qualidade como Ótimo, Bom, Medíocre ou Ruim. Essa métrica de avaliação fornece uma indicação aproximada da saúde do servidor, mas não deve ser vista como absoluta. Por exemplo, suponha que você veja uma pontuação "medíocre" para o tempo da GPU. É considerado medíocre porque se aproxima do limite para o orçamento geral de tempo de quadro. No seu caso, no entanto, pode ser um bom valor, porque você está renderizando um modelo complexo.

Saída de depuração de estatísticas

A classe é uma classe ServiceStatistics C# que envolve as estatísticas de quadro e as consultas de avaliação de desempenho e fornece funcionalidade conveniente para retornar estatísticas como valores agregados ou como uma cadeia de caracteres pré-criada. O código a seguir é a maneira mais fácil de mostrar estatísticas do lado do servidor em seu aplicativo cliente.

ServiceStatistics _stats = null;

void OnConnect()
{
    _stats = new ServiceStatistics();
}

void OnDisconnect()
{
    _stats = null;
}

void Update()
{
    if (_stats != null)
    {
        // update once a frame to retrieve new information and build average values
        _stats.Update(Service.CurrentActiveSession);

        // retrieve a string with relevant stats information
        InfoLabel.text = _stats.GetStatsString();
    }
}

O código acima preenche o rótulo de texto com o seguinte texto:

ArrServiceStats string output

A GetStatsString API formata uma cadeia de caracteres de todos os valores, mas cada valor único também pode ser consultado programaticamente a partir da ServiceStatistics instância.

Existem também variantes dos membros, que agregam os valores ao longo do tempo. Ver membros com sufixo *Avg, *Maxou *Total. O membro FramesUsedForAverage indica quantos quadros foram usados para essa agregação.

Documentação da API

Próximos passos