Query sulle prestazioni lato server

Ottenere prestazioni di rendering ottimali sul server è essenziale per avere frequenze dei fotogrammi stabili e offrire agli utenti un'esperienza soddisfacente. È importante monitorare con attenzione le caratteristiche delle prestazioni sul server e ottimizzare laddove necessario. È possibile eseguire query sui dati sulle prestazioni usando funzioni API dedicate.

L'elemento di maggior impatto riguardo alle prestazioni di rendering è rappresentato dai dati di input del modello. È possibile modificare i dati di input come descritto in Configurare la conversione di modelli.

Anche le prestazioni delle applicazioni lato client possono costituire un collo di bottiglia. Per un'analisi approfondita delle prestazioni lato client, è consigliabile usare .performance trace

Sequenza temporale client/server

Prima di esaminare in dettaglio i vari valori di latenza, è consigliabile esaminare i punti di sincronizzazione tra client e server nella sequenza temporale:

Pipeline timeline

L'illustrazione indica che:

  • viene avviata una stima della posa dal client con una frequenza dei fotogrammi costante di 60 Hz (ogni 16,6 ms)
  • il server quindi avvia il rendering in base alla posa
  • il server restituisce l'immagine video codificata
  • il client decodifica l'immagine, esegue alcune operazioni di CPU e GPU sulla stessa e poi la visualizza

Query sulle statistiche dei fotogrammi

Le statistiche dei fotogrammi offrono alcune informazioni di alto livello per l'ultimo fotogramma, ad esempio la latenza. I dati specificati nella struttura FrameStatistics vengono misurati sul lato client, quindi l'API è una chiamata sincrona:

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
    }
}

L'oggetto FrameStatistics recuperato include i membri seguenti:

Membro Spiegazione
LatencyPoseToReceive Latenza dalla stima della posa della fotocamera nel dispositivo client al momento in cui è completamente disponibile un fotogramma del server per l'applicazione client. Questo valore include round trip della rete, tempo di rendering del server, decodifica video e compensazione dell'instabilità. Vedere l'intervallo 1 nell'illustrazione precedente.
LatencyReceiveToPresent Latenza dalla disponibilità di un fotogramma ricevuto in remoto al momento in cui l'app client chiama PresentFrame sulla CPU. Vedere l'intervallo 2 nell'illustrazione precedente.
LatencyPresentToDisplay Latenza dalla presentazione di un fotogramma sulla CPU fino all'attivazione del display. Questo valore include tempo GPU client, qualsiasi buffer dei fotogrammi eseguito dal sistema operativo, riproiezione hardware e tempo di analisi del display dipendente dal dispositivo. Vedere l'intervallo 3 nell'illustrazione precedente.
TimeSinceLastPresent Intervallo di tempo tra le chiamate successive a PresentFrame sulla CPU. I valori superiori alla durata della visualizzazione, ad esempio 16,6 ms in un dispositivo client a 60 Hz, indicano i problemi causati dall'applicazione client che non termina in tempo il carico di lavoro della CPU.
VideoFramesReceived Numero di fotogrammi ricevuti dal server nell'ultimo secondo.
VideoFrameReusedCount Numero di fotogrammi ricevuti nell'ultimo secondo che sono stati usati più volte nel dispositivo. I valori diversi da zero indicano che i fotogrammi devono essere riutilizzati e riproiettati a causa di un'instabilità della rete o di un tempo di rendering eccessivo del server.
VideoFramesSkipped Numero di fotogrammi ricevuti nell'ultimo secondo che sono stati decodificati, ma non visualizzati sul display perché è arrivato un fotogramma più recente. I valori diversi da zero indicano che l'instabilità della rete ha causato il ritardo di più fotogrammi che poi sono arrivati nel dispositivo client tutti insieme.
VideoFramesDiscarded Molto simile a VideoFramesSkipped, ma il motivo per essere scartato è che un fotogramma è arrivato così tardi che non può nemmeno essere correlato con qualsiasi posa in sospeso. In questo caso, si verifica un conflitto di rete grave.
VideoFrameMinDelta Quantità minima di tempo tra due fotogrammi consecutivi in arrivo nell'ultimo secondo. Insieme a VideoFrameMaxDelta, questo intervallo fornisce un'indicazione di instabilità causata dal codec di rete o video.
VideoFrameMaxDelta Quantità massima di tempo tra due fotogrammi consecutivi in arrivo nell'ultimo secondo. Insieme a VideoFrameMinDelta, questo intervallo fornisce un'indicazione del jitter causato dal codec di rete o video.

La somma di tutti i valori di latenza è in genere molto maggiore rispetto alla durata dei fotogrammi disponibili a 60 Hz. Questo è accettabile, poiché vengono distribuiti più fotogrammi in parallelo e le nuove richieste di fotogrammi vengono avviate alla frequenza dei fotogrammi desiderata, come illustrato nella figura. Tuttavia, se la latenza diventa troppo grande, influisce sulla qualità della riproiezione con ritardo della fase e può compromettere l'esperienza complessiva.

VideoFramesReceived, VideoFrameReusedCount e VideoFramesDiscarded possono essere usati per misurare le prestazioni della rete e del server. Una combinazione di un valore basso VideoFramesReceived e un valore elevato VideoFrameReusedCount può indicare la congestione della rete o prestazioni del server scarse. Un valore VideoFramesDiscarded elevato indica anche la congestione della rete.

Infine, TimeSinceLastPresent, VideoFrameMinDelta e VideoFrameMaxDelta danno un'idea della varianza dei fotogrammi video in arrivo e delle chiamate locali presenti. Una varianza elevata indica una frequenza dei fotogrammi instabile.

Nessuno dei valori precedenti offre un'indicazione chiara della latenza di rete pura (le frecce rosse nell'illustrazione), perché l'ora esatta in cui il server è occupato con il rendering deve essere sottratto dal valore di round trip LatencyPoseToReceive. La parte lato server della latenza complessiva è costituita da informazioni non disponibili per il client. Tuttavia, il paragrafo successivo spiega come questo valore viene approssimativo tramite input aggiuntivo dal server ed esposto tramite il NetworkLatency valore .

Query di valutazione delle prestazioni

Le query di valutazione delle prestazioni offrono informazioni più dettagliate sul carico di lavoro di CPU e GPU sul server. Poiché i dati vengono richiesti dal server, l'esecuzione di query su uno snapshot delle prestazioni segue il consueto modello asincrono:

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...
        }
    });
}

Contrariamente all'oggetto FrameStatistics, l'oggetto PerformanceAssessment contiene informazioni sul lato server:

Membro Spiegazione
TimeCPU Tempo medio CPU server per fotogramma in millisecondi
TimeGPU Tempo medio GPU server per fotogramma in millisecondi
UtilizationCPU Utilizzo CPU totale nel server in percentuale
UtilizationGPU Utilizzo GPU totale nel server in percentuale
MemoryCPU Utilizzo totale della memoria principale nel server in percentuale
MemoryGPU Utilizzo totale della memoria video dedicata in percentuale della GPU del server
NetworkLatency Latenza media di rete approssimativa del round trip in millisecondi. Nella figura precedente questo valore corrisponde alla somma delle frecce rosse. Il valore viene calcolato sottraendo il tempo effettivo di rendering del server dal valore LatencyPoseToReceive di FrameStatistics. Anche se questa approssimazione non è accurata, fornisce un'indicazione della latenza di rete, isolata dai valori di latenza calcolati nel client.
PoligoniRendered Numero di triangoli sottoposti a rendering in un fotogramma. Questo numero include anche i triangoli che vengono selezionati in seguito durante il rendering. Ciò significa che questo numero non varia molto in diverse posizioni della fotocamera, ma le prestazioni possono variare drasticamente, a seconda della frequenza di limitazione dei triangoli.
PointsRendered Numero di punti nelle nuvole di punti di cui viene eseguito il rendering in un fotogramma. Gli stessi criteri di scellino indicati in precedenza per PolygonsRendered l'applicazione qui.

Per facilitare la valutazione dei valori, ogni parte viene classificata in base alla qualità, ad esempio Great, Good, Mediocre o Bad. Questa metrica di valutazione fornisce un'indicazione approssimativa dell'integrità del server, ma non deve essere considerata assoluta. Si supponga, ad esempio, che venga visualizzato il punteggio "mediocre" per il tempo GPU. È considerato mediocre perché si avvicina al limite per il budget complessivo del periodo di tempo. In questo caso, tuttavia, potrebbe essere un buon valore, perché si esegue il rendering di un modello complesso.

Output del debug delle statistiche

La classe ServiceStatistics è una classe C# che esegue il wrapping delle statistiche dei fotogrammi e delle query sulla valutazione delle prestazioni e offre una comoda funzionalità per restituire le statistiche come valori aggregati o come stringa predefinita. Il codice seguente rappresenta il modo più semplice per visualizzare le statistiche sul lato server nell'applicazione client.

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();
    }
}

Il codice precedente popola l'etichetta di testo con il testo seguente:

ArrServiceStats string output

L'API GetStatsString formatta una stringa di tutti i valori, ma ogni singolo valore può anche essere sottoposto a query a livello di codice dall'istanza di ServiceStatistics.

Sono inoltre disponibili varianti dei membri che aggregano i valori nel tempo. Vedere i membri con suffisso *Avg, *Max o *Total. Il membro FramesUsedForAverage indica il numero di fotogrammi usati per questa aggregazione.

Documentazione sull'API

Passaggi successivi