Qt измеряет время рендеринга, в течение которого приложение заморожено - PullRequest
2 голосов
/ 07 апреля 2020

У меня есть приложение Qt, где, среди прочего, есть функция render, которая просматривает список объектов и создает для каждого соответствующее (в подклассе) QGraphicsPathItem, которое оно затем помещает как дочерний элемент в (в подклассе) QGraphicsScene. (Это делается в приведенном ниже коде через посетителя GGObjConstructor, который инициализируется переменной scene, которая является сценой, в которую нужно добавить элементы).

XTimer timer;

timer.start();

gobjlist gobjlis = ogc._gobjectlis;

GGObjConstructor ggoc(scene, z_value, bkground_color);

for(auto obj: gobjlis) {
    obj->exec( &ggoc );
}

timer.stop();

Мой класс XTimer очевидным образом используется для измерения времени этого процесса.

Теперь проблема в следующем: только время, потраченное в l oop, где все предметы подготовлены и вставлены в сцену, измеряется timer. Для типичного примера с ~ 165000 элементов это дает около 7.5 se c в качестве значения таймера при достижении timer.stop(). Но приложение после этих 7.5 se c все еще заморожено, с экранным окном, в котором сцена должна отображаться, но невидимым, и только после примерно 25 se c (с ручной остановкой) внезапно появляется окно отображения со всеми элементы для отображения.

Теперь, конечно, я хотел бы измерить это «время замораживания» (или время, пока приложение снова не станет отзывчивым, или, возможно, время, пока не появится окно отображения). Но я не нашел способа сделать это, хотя я некоторое время просматривал stackoverflow или net в целом. Лучший совет, который я нашел, был

stackoverflow вопрос

Ответ, по-видимому, подразумевал, что это будет не очень просто достичь (переопределение метода paintEvent и тому подобное) ,

Вопрос: это правда? Или есть простой способ измерить время, пока приложение снова не станет отзывчивым / изображение действительно отображается?

1 Ответ

1 голос
/ 08 апреля 2020

Однажды у меня была похожая проблема с приложением, когда я хотел измерить время, в течение которого приложение зависает, чтобы выяснить, регистрируя, что вызывает эти зависания. Я придумал, как измерить, как долго Eventl oop основной темы не отвечал, потому что это напрямую соответствует замороженному приложению.

Основная идея c - не запускать QApplication но наследовать от QApplication и переопределять функцию notify(). В любом случае некоторые приложения делают это, чтобы перехватить исключения, которые в противном случае прервали бы событие l oop. Вот некоторый псевдокод, который должен донести эту идею:

bool MyApplication::notify( QObject * receiver, QEvent *  event ) 
{
    // something like storing current time like:
    // auto start = std::chrono::system_clock::now();
    // auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(start - end );
    // if( elapsed.count() > 1000 ){
    // log something like: Mainthread responds again after <elapsed> seconds
    // }
    // Note that end must be a member variable
    // end = start;
    return QApplication::notify(receiver, event);
}

Примечание 1. Если ваше приложение не работает постоянно через notify(), вы можете для целей тестирования ввести пустышку QTimer, которая срабатывает быстрее чем порог времени регистрации.

Примечание 2: если вы используете несколько потоков, особенно QThreads может потребоваться отфильтровать объект receiver и выполнить этот код только в том случае, если получатель находится в основной потоке.

С помощью этого кода вы можете регистрировать каждое зависание основного потока (заморожено GUI) и определить продолжительность заморозки. При правильном ведении журнала вы можете выяснить, что вызывает зависание. Имейте в виду, что это будет регистрироваться только после разрешения замораживания!

Добавление: Это сложнее и медленнее, но для целей отладки / исследования вы можете сохранить последнее событие и Object- Дерево получателя и лог, а также. Чем вы даже знаете, что было последним событием, которое вызвало замораживание и получение объекта.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...