LINUX.ORG.RU

Как оптимизировать отрисовку сцены?

 , ,


0

3

Добрый день!

У меня есть сцена, которая активно перерисовывается при взаимодействии.

Индексация сцены отключена.

Когда на ней становится много объектов, она начинает перерисовывать чуть медленней. Вроде всё логично, но есть одно НО

Я делал сборку под Linux на компиляторе GCC на версии Qt5.12.11 Под Windows собирал на MSVC17 64bit

И сборка на Линукс (GCC) работает гораздо быстрей, чем под Windows(MSVC17)…

Начал делать замеры скорости выполнения функций и наткнулся на странность:

Функция:

/* Функция перерисования вертикальных осей */
void Viewer::RedrawTimeAxes()
{
    QTime timer;
    timer.start();
    deleteItemsGroup(grTimeAxes);
    int stepInAxis = projectGID->timeAxes.stepAxis;
    // Берем из настроек шаг.
    int stepMinutes = cofigGID->stepMinets();
    //Скролл по минуте
    QDateTime tempDateTime = cofigGID->startDateTime();
//    qDebug() << ">>>>>>[Ведем просмотр даты] " << cofigGID->startDateTime() << "]";
    // Определяем минуту даты.
    int currentMinute = tempDateTime.time().minute();
    // Определяем час даты
    int currentHour = tempDateTime.time().hour();
    /* Находим след. интервал кратный шагу. Прим. Для шага 5: 44 минуты(след 45), 02 минуты(след 05) итд */
    //(Прим: currentMinute = 47, stepMinutes = 5, 47 - (47%5) + 5 = 50
    int nextMinuteStep =  currentMinute - (currentMinute % stepMinutes) + stepMinutes;
    // Находим недостаток минут до след. шага. (Прим: stepMinutes=5, currentMinute=47 => nextMinuteStep = 50)
    //                                         (Прим: stepMinutes=15,currentMinute=47 => nextMinuteStep = 0)
    int offsetMinutes = nextMinuteStep - currentMinute;
    // Переводим отступ в пиксели
    qreal offsetInPixels = (qreal(stepInAxis) / stepMinutes) * offsetMinutes;
//    qDebug() << "StepInAxis = " << stepInAxis << "...StepMinutes= " << stepMinutes << "...offsetMinutes = " << offsetMinutes;
    // Зануляем количество видимых осей
    projectGID->timeAxes.countAxes = 0;
    qDebug() << "Расчеты произведены за " << timer.elapsed() << " мс";
    QTime timer2;
    timer2.start();
    qDebug() << "[НАЧАЛО ОТРИСОВКИ ОСЕЙ]";
    qreal nStep = offsetInPixels;
    while( nStep < scene()->width() )
    {
        /* определяем значение отрисовываемой минуты */
        int currentMinuteDraw = nextMinuteStep % SECONDS_IN_MINUTE;
        /* определяем значение отрисовываемого часа. */
        int currentHourDraw = (currentHour + (nextMinuteStep / SECONDS_IN_MINUTE)) % HOURS_IN_DAY;
        qreal xPos = nStep;
//        int yPos = projectGID->rcGidPlan.height() - fmsGid->height() - m_offsetTimeScaleScene;

        /* Проверяем если отрисовочная минута == 0, значит отрисовываем час */
        if (currentMinuteDraw == 0) {
            QTime timerHour;
            timerHour.start();
            DrawVerticalAxeHour(xPos, currentHourDraw);
            qDebug() << "Часовая ось отрисовалась за : " << timerHour.elapsed() << " мс";
        } else {
            QTime timerMinute;
            timerMinute.start();
            DrawVerticalAxeMinute(xPos, currentMinuteDraw);
            qDebug() << "Минутная ось отрисована за : " << timerMinute.elapsed() << " мс";
        }

        /*Отрисовываем текущую дату*/
        QTime timerDate;
        timerDate.start();
        DrawWatchingDate();
        qDebug() << "Время отрисовки даты: " << timerDate.elapsed() << " мс";
        /* Переводим nextTimeStep дальше по шагу */
        nextMinuteStep = nextMinuteStep + cofigGID->stepMinets();
        // Пополняем количество нарисованных осей
        projectGID->timeAxes.countAxes++;
        nStep += projectGID->timeAxes.stepAxis;
    }
    qDebug() << "Цикл отрисовки произведен за : " << timer2.elapsed() << " мс";
    // Расчитываем последнюю дату просмотра
    lastWatchingTime = cofigGID->startDateTime().addSecs(cofigGID->secondsInPixel(projectGID->timeAxes.stepAxis) * scene()->width() + SECONDS_IN_MINUTE);
    // Зануляем секунды
    lastWatchingTime.setTime(QTime(lastWatchingTime.time().hour(), lastWatchingTime.time().minute()));
//    qDebug() << "<<<[APPROXIMATE END WATCH DATA] " << lastWatchingTime;
    /* отрисовка горизональной линии разделяющую сцену шкалы времени от сцены санций и сетки ГИД */
    const int yPosSeparator = projectGID->rcGidPlan.height() - m_offsetTimeScaleScene - fmsGid->height()*2;
    grTimeAxes->addToGroup(scenePlan->addLine(0, yPosSeparator, scenePlan->width() - 1, yPosSeparator, QPen(palette().color(foregroundRole()))));
    qDebug() << "=====КОЛИЧЕСТВО ЭЛЕМЕНТОВ======" << scene()->items().count();
    qDebug() << "Полный цикл отрисовки : " << timer.elapsed() << " мс";
}

Функция DrawVerticalAxeMinute

/* Отрисовка вертикальной МИНУТНОЙ ОСИ */
void Viewer::DrawVerticalAxeMinute(qreal xPos, int minuteDraw)
{
    QFont font(cofigGID->font);
    /* Вычисляем высоту для минут */
    int yPos = projectGID->rcGidPlan.height() - fmsGid->height()*2 - m_offsetTimeScaleScene;
    QTime timerAddGroup;
    timerAddGroup.start();
    auto line = scenePlan->addLine(xPos, 0, xPos, yPos,
                                   cofigGID->lineScaleStep.pen());
    qDebug() << ">[МИНУТНЫЕ ОСИ]ДОБАВЛЯЕМ ЛИНИЮ НА СЦЕНУ " << timerAddGroup.elapsed() << " мс";
    timerAddGroup.restart();
    grTimeAxes->addToGroup(line);
    qDebug() << "<[МИНУТНЫЕ ОСИ]ДОБАВЛЕНО В ГРУППУ " << timerAddGroup.elapsed() << " мс";
    font.setBold(false);
    timerAddGroup.restart();
    auto text = scenePlan->drawText(
                QString("%0").arg(minuteDraw),
                /*  Выравнивание, если у нас отрисовываемая минута < 10 (для одного числа съезжает чуть-чуть, поэтому делим на 4, если >10, то делим на 2)*/
                /*xPos*/(minuteDraw < 10) ? (xPos - fmsGid->height() / 4) : (xPos - fmsGid->height() / 2),
                                       yPos, font, cofigGID->clrFont.color());
    qDebug() << ">>[Минутные ОСИ]ДОБАВЛЕН ТЕКСТ" << timerAddGroup.elapsed() << " мс";
    timerAddGroup.restart();
    grTimeAxes->addToGroup(text);
    qDebug() << ">>[МИНУТНЫЕ ОСИ]Добавление в группу2 происходило " << timerAddGroup.elapsed() << " мс";
}

В windows Начинает работать дольше на функции, которая первая добавит элемент на сцену/добавит в графическую группу( и будет долго работать всего один раз) следующие разы, уже отрабатывает как на linux..

А на Linux быстро и сразу(причем даже объекты гораздо большие, отрисовывает гораздо быстрей)…

Ссылка на логи(визуально глянуть) : https://postimg.cc/gallery/D1VRCpt

Логи физические: https://dropmefiles.com/IF3TU



Последнее исправление: Nikci12 (всего исправлений: 2)

ты, прежде чем напрягать публику своими портянками, выбери методику измерения.

твой

QTime timer;

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

что там у вас в Кутэ показывает время работы процесса - без понятия, сам ищи.

alysnix ★★★
()
Ответ на: комментарий от XMs

это то же, что было у него. астрономическое время.

пользовать надо std::clock!!! - это клоки планировщика, которые работал данный процесс.

а не астрономическое время, затраченное ВСЕМИ ПРОЦЕССАМИ И ПРОЧИМИ АКТИВНОСТЯМИ в системе.

клоки системы, получаются из таймерных прерываний, и эти клоки, затраченные процессом, считает планировщик ядра. вот они и показывают реальную производительность вашей проги.

alysnix ★★★
()
Последнее исправление: alysnix (всего исправлений: 1)
Ответ на: комментарий от ya-betmen

К сожалению нельзя. Сетка перерисовывается постоянно, поэтому не получится :(

Глючит именно когда зажимаю и перемещаю мышь. (У меня при зажатой ЛКМ и перемещении мыши перерисовывается сцена сетка(полностью удаляется и заново создается ~300 объектов) и потом через setPos перемещаются объекты в группе(их может быть от 0 до бесконечности, подтормаживает когда их 2000+ (но в это если в винде, линька и 3000+ спокойно рисует))).

Я посмотрел стек вызовов. На линуксе - 26 вызовов, на винде 36. Думаю напартачил где-то с обработчиками mouseMoveEvent

У меня во Вьюшке свой обработчик mouseMoveEvent и у сцены(свой переопределенный тоже есть)…

Nikci12
() автор топика