Zapytania wydajności po stronie serwera
Dobra wydajność renderowania na serwerze ma kluczowe znaczenie dla stabilnych szybkości klatek i dobrego środowiska użytkownika. Ważne jest, aby dokładnie monitorować charakterystykę wydajności na serwerze i w razie potrzeby zoptymalizować. Dane wydajności mogą być odpytywane za pomocą dedykowanych funkcji interfejsu API.
Najbardziej wpływ na wydajność renderowania to dane wejściowe modelu. Dane wejściowe można dostosować zgodnie z opisem w temacie Konfigurowanie konwersji modelu.
Wydajność aplikacji po stronie klienta może być również wąskim gardłem. Aby uzyskać szczegółową analizę wydajności po stronie klienta, zaleca się wykonanie operacji performance trace.
Oś czasu klienta/serwera
Zanim przejdziesz do szczegółów dotyczących różnych wartości opóźnienia, warto zapoznać się z punktami synchronizacji między klientem a serwerem na osi czasu:
Na ilustracji pokazano, jak:
- Oszacowanie pose jest uruchamiane przez klienta z stałą szybkością klatek 60-Hz (co 16,6 ms)
- następnie serwer uruchamia renderowanie na podstawie pozy
- serwer wysyła z powrotem zakodowany obraz wideo
- klient dekoduje obraz, wykonuje niektóre operacje procesora CPU i procesora GPU na nim, a następnie wyświetla obraz
Zapytania statystyk ramek
Statystyki ramek zapewniają pewne informacje wysokiego poziomu dla ostatniej ramki, takie jak opóźnienie. Dane podane w FrameStatistics
strukturze są mierzone po stronie klienta, więc interfejs API jest synchronicznym wywołaniem:
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
}
}
Pobrany FrameStatistics
obiekt zawiera następujące elementy członkowskie:
Element członkowski | Wyjaśnienie |
---|---|
OpóźnieniePoseToReceive | Opóźnienie z aparatu stanowi oszacowanie na urządzeniu klienckim, dopóki ramka serwera dla tej pozy jest w pełni dostępna dla aplikacji klienckiej. Ta wartość obejmuje roundtrip sieci, czas renderowania serwera, dekodowanie wideo i kompensację zakłócenia. Zobacz interwał 1 na powyższej ilustracji. |
OpóźnienieReceiveToPresent | Opóźnienie z dostępności odebranej ramki zdalnej do momentu wywołania elementu PresentFrame przez aplikację kliencką na procesorze CPU. Zobacz interwał 2 na powyższej ilustracji. |
LatencyPresentToDisplay | Opóźnienie podczas prezentowania ramki na procesorze do momentu zaświetlania wyświetlacza. Ta wartość obejmuje czas procesora GPU klienta, buforowanie ramek wykonywane przez system operacyjny, ponowne projekty sprzętowe i czas skanowania wyświetlania zależnego od urządzenia. Zobacz interwał 3 na powyższej ilustracji. |
TimeSinceLastPresent | Czas między kolejnymi wywołaniami elementu PresentFrame na procesorze CPU. Wartości większe niż czas trwania wyświetlania (na przykład 16,6 ms na urządzeniu klienckim 60-Hz) wskazują problemy spowodowane przez aplikację kliencką, która nie kończy obciążenia procesora CPU w czasie. |
VideoFramesReceived | Liczba ramek odebranych z serwera w ciągu ostatniej sekundy. |
VideoFrameReusedCount | Liczba odebranych ramek w ciągu ostatniej sekundy, które były używane na urządzeniu więcej niż raz. Wartości inne niż zero wskazują, że ramki musiały być ponownie używane i ponownie projektowane z powodu zakłócenia sieci lub nadmiernego czasu renderowania serwera. |
VideoFramesSkipped | Liczba odebranych ramek w ciągu ostatniej sekundy, które zostały zdekodowane, ale nie są wyświetlane na wyświetlaczu, ponieważ przybyła nowsza ramka. Wartości inne niż zero wskazują, że zakłócenia sieci spowodowały opóźnienie wielu ramek, a następnie przybyć na urządzeniu klienckim razem w serii. |
VideoFramesDiscarded | Bardzo podobne do VideoFramesSkipped, ale powodem odrzucenia jest to, że ramka pojawiła się tak późno, że nie może być nawet skorelowana z żadną oczekującą pozą. W przypadku tego odrzucenia występuje poważna rywalizacja sieciowa. |
VideoFrameMinDelta | Minimalny czas między dwoma kolejnymi ramkami przybywającymi w ciągu ostatniej sekundy. Wraz z videoFrameMaxDelta ten zakres wskazuje na zakłócenia spowodowane przez sieć lub koder wideo. |
VideoFrameMaxDelta | Maksymalny czas między dwoma kolejnymi ramkami przybywającymi w ciągu ostatniej sekundy. Wraz z elementem VideoFrameMinDelta ten zakres wskazuje na zakłócenia spowodowane przez sieć lub koder wideo. |
Suma wszystkich wartości opóźnienia jest zwykle znacznie większa niż dostępny czas ramki na 60 Hz. Jest to ok, ponieważ wiele ramek jest w locie równolegle, a nowe żądania klatek są uruchamiane z żądaną szybkością klatek, jak pokazano na ilustracji. Jednak jeśli opóźnienie stanie się zbyt duże, wpływa na jakość ponownego projektu na późnym etapie i może naruszyć ogólne środowisko.
VideoFramesReceived
, VideoFrameReusedCount
i VideoFramesDiscarded
może służyć do pomiaru wydajności sieci i serwera. Połączenie niskiej VideoFramesReceived
wartości i wysokiej VideoFrameReusedCount
wartości może wskazywać na przeciążenie sieci lub niską wydajność serwera. Wysoka VideoFramesDiscarded
wartość wskazuje również przeciążenie sieci.
Na koniecTimeSinceLastPresent
, VideoFrameMinDelta
, i VideoFrameMaxDelta
dać pojęcie wariancji przychodzących ramek wideo i lokalnych obecnych wywołań. Wysoka wariancja oznacza szybkość ramki w tabeli.
Żadna z powyższych wartości nie wskazuje na czyste opóźnienie sieci (czerwone strzałki na ilustracji), ponieważ dokładny czas, w jaki serwer jest zajęty renderowaniem, musi zostać odjęty od wartości LatencyPoseToReceive
dwukierunkowej . Część ogólnego opóźnienia po stronie serwera to informacje, które są niedostępne dla klienta. W następnym akapicie wyjaśniono jednak, w jaki sposób ta wartość jest przybliżona przez dodatkowe dane wejściowe z serwera i uwidoczniona za pośrednictwem NetworkLatency
wartości.
Zapytania dotyczące oceny wydajności
Zapytania dotyczące oceny wydajności zawierają bardziej szczegółowe informacje o obciążeniu procesora CPU i procesora GPU na serwerze. Ponieważ dane są żądane z serwera, wykonywanie zapytań dotyczących migawki wydajności jest zgodne ze zwykłym wzorcem asynchronicznym:
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...
}
});
}
W przeciwieństwie do FrameStatistics
obiektu obiekt PerformanceAssessment
zawiera informacje po stronie serwera:
Element członkowski | Wyjaśnienie |
---|---|
TimeCPU | Średni czas procesora CPU serwera na ramkę w milisekundach |
TimeGPU | Średni czas procesora GPU serwera na ramkę w milisekundach |
Użycie procesora CPUU | Łączne wykorzystanie procesora CPU serwera w procentach |
Użycie procesoraGPU | Łączne wykorzystanie procesora GPU serwera w procentach |
Procesor pamięci | Całkowite wykorzystanie pamięci głównej serwera w procentach |
PamięćGPU | Całkowite wykorzystanie pamięci wideo w procentach procesora GPU serwera |
Opóźnienie sieci | Przybliżone średnie opóźnienie sieci w obie strony w milisekundach. Na powyższej ilustracji ta wartość odpowiada sumie czerwonych strzałek. Wartość jest obliczana przez odjęcie rzeczywistego LatencyPoseToReceive FrameStatistics czasu renderowania serwera z wartości . Chociaż to przybliżenie nie jest dokładne, daje pewne wskazanie opóźnienia sieci, odizolowane od wartości opóźnień obliczonych na kliencie. |
WielokątyRenderowane | Liczba trójkątów renderowanych w jednej ramce. Ta liczba obejmuje również trójkąty, które zostaną później uśmierczone podczas renderowania. Oznacza to, że ta liczba nie różni się znacznie w różnych pozycjach aparatu, ale wydajność może się znacząco różnić, w zależności od współczynnika uścisk trójkąta. |
PointRendered | Liczba punktów w chmurach punktowych renderowanych w jednej ramce. Te same kryteria uboju, jak wspomniano powyżej, mają PolygonsRendered zastosowanie tutaj. |
Aby ułatwić ocenę wartości, każda część zawiera klasyfikację jakości, na przykład Great, Good, Mediocre lub Bad. Ta metryka oceny zapewnia przybliżone wskazanie kondycji serwera, ale nie powinna być postrzegana jako bezwzględna. Załóżmy na przykład, że zobaczysz wynik "przeciętny" dla czasu procesora GPU. Jest to uważane za przeciętne, ponieważ zbliża się do limitu ogólnego budżetu czasu. Jednak w Twoim przypadku może to być dobra wartość, ponieważ renderujesz złożony model.
Dane wyjściowe debugowania statystyk
Klasa jest klasą ServiceStatistics
języka C#, która opakowuje zarówno statystyki ramki, jak i zapytania oceny wydajności oraz zapewnia wygodne funkcje zwracania statystyk jako zagregowanych wartości lub jako wstępnie skompilowanego ciągu. Poniższy kod jest najprostszym sposobem wyświetlania statystyk po stronie serwera w aplikacji klienckiej.
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();
}
}
Powyższy kod wypełnia etykietę tekstową następującym tekstem:
Interfejs GetStatsString
API formatuje ciąg wszystkich wartości, ale każda pojedyncza wartość może być również odpytywane programowo z ServiceStatistics
wystąpienia.
Istnieją również warianty elementów członkowskich, które agregują wartości w czasie. Zobacz elementy członkowskie z sufiksem *Avg
, *Max
lub *Total
. Element członkowski FramesUsedForAverage
wskazuje, ile ramek zostało użytych do tej agregacji.
Dokumentacja interfejsu API
- Renderowanie w języku C#Połączenie ion. QueryServerPerformanceAssessmentAsync()
- Renderowanie języka C++Połączenie ion::QueryServerPerformanceAssessmentAsync()