Запросы данных производительности на стороне сервера
Правильная производительность отрисовки на сервере крайне важна для стабильной частоты кадров и обеспечения эффективного взаимодействия с пользовательским интерфейсом. Важно тщательно отслеживать характеристики производительности на сервере и при необходимости оптимизировать их. Данные производительности можно запрашивать с помощью выделенных функций API.
Наибольшее влияние на производительность отрисовки оказывают входные данные модели. Сведения о настройке входных данных см. в статье Настройка преобразования модели.
Производительность приложений на стороне клиента также может быть узким местом. Для подробного анализа производительности на стороне клиента рекомендуется использовать performance trace.
Временная шкала клиента и сервера
Прежде чем подробно ознакомиться с различными значениями задержки, стоит ознакомиться с точками синхронизации между клиентом и сервером на временная шкала:
На рисунке показано как:
- оценка положения запускается клиентом при постоянной частоте кадров 60 Гц (каждые 16,6 мс);
- затем сервер запускает отрисовку на основе положения;
- сервер отправляет обратно закодированное видеоизображение;
- клиент декодирует изображение, выполняет над ним некоторую работу ЦП и GPU, а затем показывает образ.
Запросы данных о статистике кадров
В статистике кадров предоставлены некоторые важные сведения о последнем кадре, например задержка. Данные, предоставленные в структуре FrameStatistics
, измеряются на стороне клиента, поэтому API является синхронным вызовом:
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
}
}
Полученный объект FrameStatistics
содержит следующие элементы:
Элемент | Описание |
---|---|
LatencyPoseToReceive | Задержка оценки положения камеры на устройстве клиента происходит до тех пор, пока кадр сервера для этого положения не будет полностью доступен клиентскому приложению. Это значение содержит цикл обращений по сети, время преобразования сервера для просмотра, сведения о декодировании видео и компенсации дрожания. См. интервал 1 на приведенной выше иллюстрации. |
LatencyReceiveToPresent | Задержка доступности полученного удаленного кадра происходит до тех пор, пока клиентское приложение не вызовет PresentFrame в ЦП. См. интервал 2 на приведенной выше иллюстрации. |
LatencyPresentToDisplay | Задержка предоставления кадра в ЦП происходит до тех пор, пока не загорится экран. Это значение содержит время GPU клиента, любую буферизацию кадров, выполняемую операционной системой, и время считывания данных с дисплея, зависящее от устройства. См. интервал 3 на приведенной выше иллюстрации. |
TimeSinceLastPresent | Время между последовательными вызовами PresentFrame в ЦП. Значения, превышающие длительность отображения (например, 16,6 мс на клиентском устройстве с частотой 60 Гц), указывают на проблемы, вызванные тем, что клиентское приложение не завершило рабочую нагрузку ЦП вовремя. |
VideoFramesReceived | Число кадров, полученных с сервера за последнюю секунду. |
VideoFrameReusedCount | Число полученных кадров за последнюю секунду, которые использовались на устройстве несколько раз. Ненулевые значения указывают на то, что кадры пришлось повторно использовать и репроецировать из-за дрожаний в сети или длительной отрисовки сервера. |
VideoFramesSkipped | Число полученных кадров за последнюю секунду, которые были декодированы, но не показаны на экране, так как поступил более новый кадр. Ненулевые значения указывают на то, что дрожание в сети привело к задержке нескольких кадров, а затем поступило на клиентское устройство вместе с пакетом. |
VideoFramesDiscarded | Очень похоже на videoFramesSkipped, но причина отмены заключается в том, что кадр поступил так поздно, что его уже нельзя коррелировать с каким-либо ожидающим положением. Если это не карта происходит, есть некоторые серьезные проблемы сети. |
VideoFrameMinDelta | Минимальное количество времени между двумя последовательными кадрами, поступающими за последнюю секунду. Вместе с VideoFrameMaxDelta этот диапазон указывает на дрожание, вызванное либо сетью, либо видеокодеком. |
VideoFrameMaxDelta | Максимальное количество времени между двумя последовательными кадрами, поступающими за последнюю секунду. Вместе с videoFrameMinDelta этот диапазон указывает на дрожание, вызванное либо сетью, либо видеокодеком. |
Сумма всех значений задержки обычно гораздо больше, чем доступное время кадра с частотой 60 Гц. Это нормально, так как к нескольким кадрам предоставлен параллельный доступ, а новые запросы к кадрам запускаются с требуемой частотой, как показано на рисунке. Однако если задержка станет слишком большой, она повлияет на качество перепроецирования на позднем этапе и может нарушить общую работу.
VideoFramesReceived
, VideoFrameReusedCount
и VideoFramesDiscarded
можно использовать для производительности сети и сервера датчика. Сочетание низкого VideoFramesReceived
и высокого значения VideoFrameReusedCount
может указывать на перегрузку сети или низкую производительность сервера. Высокое значение VideoFramesDiscarded
также указывает на перегрузку сети.
Наконец, TimeSinceLastPresent
, VideoFrameMinDelta
и VideoFrameMaxDelta
дают общее представление о вариантности входящих видеокадров и локальных текущих вызовах. Высокая вариантность означает нестабильную частоту кадров.
Ни одно из приведенных выше значений четко не указывает на чистую задержку сети (красные стрелки на рисунке), так как точное время выполнения отрисовки сервером необходимо вычесть из значения цикла LatencyPoseToReceive
. Информация об общей задержке на стороне сервера недоступна для клиента. Однако следующий абзац объясняет, как это значение приблизительно через дополнительные входные данные с сервера и предоставляется через NetworkLatency
значение.
Запросы для оценки производительности
Запросы для оценки производительности предоставляют более подробные сведения о рабочей нагрузке ЦП и GPU на сервере. Так как данные запрашиваются с сервера, запрос моментального снимка показателей производительности соответствует обычному асинхронному шаблону:
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...
}
});
}
В отличие от объекта FrameStatistics
, объект PerformanceAssessment
содержит сведения на стороне сервера:
Элемент | Описание |
---|---|
TimeCPU | Среднее время ЦП сервера на кадр в миллисекундах |
TimeGPU | Среднее время GPU сервера на кадр в миллисекундах |
UtilizationCPU | Общее использование ЦП в процентах |
UtilizationGPU | Общее использование GPU в процентах |
MemoryCPU | Общее использование основной памяти сервера в процентах |
MemoryGPU | Общее использование выделенной видеопамяти в процентах на сервере GPU |
NetworkLatency | Приблизительная средняя цикличная задержка сети в миллисекундах. На приведенном выше рисунке значение соответствует сумме красных стрелок. Значение вычисляется путем вычитания фактического времени отрисовки на сервере из значения LatencyPoseToReceive в FrameStatistics . Хотя это приближение не является точным, он указывает на задержку сети, изолированную от значений задержки, вычисляемых на клиенте. |
PolygonsRendered | Число треугольников, преобразуемых для просмотра в одном кадре. Сюда также относятся треугольники, которые исключаются во время подготовки к просмотру. Это означает, что это число не зависит от разных позиций камеры, но производительность может резко отличаться в зависимости от скорости выбрасывания треугольника. |
PointsRendered | Количество точек в точках облаков, отрисованных в одном кадре. Те же критерии выбрасывания, что и упоминание выше для PolygonsRendered применения здесь. |
Чтобы помочь вам оценить значения, у каждого из них есть классификация качества, например Great (Отлично), Good (Хорошо), Mediocre (Средне) или Bad (Плохо). Эта метрика оценки предоставляет грубое представление о работоспособности сервера, но оно не должно рассматриваться как абсолютное. Например, предположим, что для времени GPU отображается оценка Mediocre "Средне". Считается посредственным, потому что он приближается к ограничению для общего бюджета времени кадров. Однако в вашем случае это может быть хорошим значением, так как вы выполняете отрисовку сложной модели.
Выходные данные отладки статистики
Класс ServiceStatistics
— это класс C#, который обтекает как статистику кадров, так и запросы для оценки производительности и предоставляет удобные функциональные возможности для возврата статистики в виде статистических значений или предварительно созданной строки. Следующий код является самым простым способом показать статистику на стороне сервера в клиентском приложении.
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();
}
}
Приведенный выше код заполняет текстовую метку следующим текстом:
API GetStatsString
форматирует строку всех значений, но каждое отдельное значение может также запрашиваться программно из экземпляра ServiceStatistics
.
Существуют также варианты элементов, которые агрегируют значения с течением времени. Ознакомьтесь с элементами с суффиксом *Avg
, *Max
или *Total
. Элемент FramesUsedForAverage
указывает, сколько кадров использовалось для этого агрегирования.
Документация по API
- C# RenderingConnection.QueryServerPerformanceAssessmentAsync()
- C++ RenderingConnection::QueryServerPerformanceAssessmentAsync()