Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

QTimer performance Qt 5.9.6 vs Qt 5.12.0



  • 20190313 Solution: passing '-platform windows:nowmpointer' parameter to QApplication (see ADD_QAPP_ARGS macro)
    https://bugreports.qt.io/browse/QTBUG-74345

    Hi,

    I moved my code from Qt 5.9.6(msvc15) to 5.12.0(msvc17) and noticed that
    QTimer slows down when I move mouse cursor over a window area (example code attached)

    When I run my example in 5.9.6 'avg' times stay at 2ms and 50ms at all times.

    When I run the example in 5.12.0 'avg' times rise during cursor movement(as well as dial update).

    This picture shows 'avg' times without cursor movement:
    0_1552228720486_cursor_not_moving.png

    This one shows 'avg' time with cursor movement. In case of QTimer period of slot calls rises from 2ms to nearly 5ms.
    0_1552228881362_cursor_moving.png

    Why this different behaviour between 5.9.6 and 5.12.0 ?
    Can someone help me solving this please ?

    Thank you !

    main.c

    #include <QApplication>
    #include "form.h"
    
    //#define ADD_QAPP_ARGS
    
    int main(int argc, char *argv[])
    {
    #if defined(ADD_QAPP_ARGS)
        char   platform  [] = "-platform";
        char   win_noptr [] = "windows:nowmpointer";
        char * add_args  [] = {argv[0], platform, win_noptr};
        if(argc == 1) {
            argc += 2;
            argv = add_args;
        }
    #endif
    
        QApplication a(argc, argv);
    
        form w;
        w.show();
    
        return a.exec();
    }
    
    

    form.cpp

    #include <QLabel>
    #include "form.h"
    #include "ui_form.h"
    
    form::form(QWidget *parent):
        QWidget(parent),
        ui(new Ui::Form)
    {
        ui->setupUi(this);
        init();
    }
    
    form::~form() { delete ui; }
    
    void form
    ::init() {
        auto qTimer {
            [this]() -> QTimer * {
                QTimer * tmr{new QTimer{this}};
                tmr->setTimerType(Qt::PreciseTimer);
                tmr->start(2);
                return tmr;}
        };
        auto qTimerSlot {
            [this]() {
                m_qtimer_slot_stats.update();
                m_sine.update();
            }
        };
    
        connect(qTimer(), &QTimer::timeout, qTimerSlot);
        m_qtimer_slot_stats.update();
    
        m_sine.set_ampl(static_cast<double>(ui->dial->maximum()));
        m_dial.update_timer_id = startTimer(50, Qt::PreciseTimer);
    }
    
    void form
    ::timerEvent(QTimerEvent *e) {
        m_timer_event_stats.update();
        e->accept();
    
        if(e->timerId() == m_dial.update_timer_id) {
            ui->dial->setValue(static_cast<int>(m_sine.smpl()));
    
            ui->lcd_qtimer_avg->display(
                QString::number(m_qtimer_slot_stats.avg_time(), 'f', 6));
            ui->lcd_qtimer_max->display(
                QString::number(m_qtimer_slot_stats.max(), 'f', 6));
            ui->lcd_qtimer_min->display(
                QString::number(m_qtimer_slot_stats.min(), 'f', 6));
    
            ui->lcd_timer_event_avg->display(
                QString::number(m_timer_event_stats.avg_time(), 'f', 6));
            ui->lcd_timer_event_max->display(
                QString::number(m_timer_event_stats.max(), 'f', 6));
            ui->lcd_timer_event_min->display(
                QString::number(m_timer_event_stats.min(), 'f', 6));
        }
    
        static volatile bool run_once {
            [this]()->bool{
                m_qtimer_slot_stats.reset_max();
                m_timer_event_stats.reset_max();
                return true;}()
        };
    }
    
    void form
    ::mousePressEvent(QMouseEvent *e) {
        e->accept();
        if(ui->lcd_qtimer_max->rect().
                contains(ui->lcd_qtimer_max->mapFrom(this, e->pos())))
            m_qtimer_slot_stats.reset_max();
        else if(ui->lcd_qtimer_min->rect().
                    contains(ui->lcd_qtimer_min->mapFrom(this, e->pos())))
            m_qtimer_slot_stats.reset_min();
        else if(ui->lcd_timer_event_max->rect().
                    contains(ui->lcd_timer_event_max->mapFrom(this, e->pos())))
            m_timer_event_stats.reset_max();
        else if(ui->lcd_timer_event_min->rect().
                    contains(ui->lcd_timer_event_min->mapFrom(this, e->pos())))
            m_timer_event_stats.reset_min();
    }
    
    

    form.h

    #ifndef FORM_H
    #define FORM_H
    
    #include <QWidget>
    #include <QMouseEvent>
    #include <QTimer>
    #include <QTimerEvent>
    #include <chrono>
    
    namespace Ui {
    class Form;
    }
    
    class form : public QWidget
    {
        Q_OBJECT
    
    public:
        explicit form(QWidget *parent = nullptr);
        ~form();
    
    private:
        void init();
    
    protected:
        void timerEvent(QTimerEvent *e);      // virtual QObject
        void mousePressEvent(QMouseEvent *e); // virtual QWidget
    
    private:
        Ui::Form * ui;
    
        struct {
            int update_timer_id {};
        } m_dial;
    
        // 'stats' class calculates info about time period between its 'update()' method calls
        class stats {
            using sc_hrc = std::chrono::high_resolution_clock;
            using sc_tp  = std::chrono::time_point<std::chrono::steady_clock>;
            using sc_du  = std::chrono::duration<double>;
            sc_tp  m_previous {sc_hrc::now()};
            double m_avg {};
            double m_max {};
            double m_min {100};
            double m_dumpling;
        public:
            explicit stats(double dumpling = .007): m_dumpling(dumpling) {}
            void update() {
                sc_du elapsed {sc_hrc::now() - m_previous};
                m_previous  = sc_hrc::now();
                if(elapsed.count() > m_max) { m_max = elapsed.count(); }
                if(elapsed.count() < m_min) { m_min = elapsed.count(); }
                m_avg += (elapsed.count() - m_avg)*m_dumpling;
            }
            double       max() { return m_max; }
            double       min() { return m_min; }
            void   reset_max() { m_max =   0;  }
            void   reset_min() { m_min = 100;  }
            double  avg_time() { return m_avg; }
        };
    
        stats m_qtimer_slot_stats {};
        stats m_timer_event_stats {.07};
    
        class {
            int    m_time {};
            double m_ampl {1.0};
            const double PI_2X_DIV_X {(2*(/*~pi*/22.0/7.0))/1500.0};
        public:
            void   set_ampl(double a) { m_ampl = a; }
            void     update() { m_time++; }
            double     smpl() { return m_ampl*std::sin(PI_2X_DIV_X*m_time); }
        } m_sine;
    };
    
    #endif // FORM_H
    
    

    speed.pro

    QT      += core gui widgets
    TARGET   = speed
    TEMPLATE = app
    DEFINES += QT_DEPRECATED_WARNINGS
    CONFIG  += c++11
    SOURCES += main.cpp form.cpp
    HEADERS += form.h
    FORMS   += form.ui
    
    

    form.ui

    <?xml version="1.0" encoding="UTF-8"?>
    <ui version="4.0">
     <class>Form</class>
     <widget class="QWidget" name="Form">
      <property name="geometry">
       <rect>
        <x>0</x>
        <y>0</y>
        <width>620</width>
        <height>240</height>
       </rect>
      </property>
      <property name="minimumSize">
       <size>
        <width>620</width>
        <height>240</height>
       </size>
      </property>
      <property name="windowTitle">
       <string>timer update test Qt 5.12.0</string>
      </property>
      <layout class="QVBoxLayout" name="verticalLayout" stretch="0">
       <property name="leftMargin">
        <number>2</number>
       </property>
       <property name="topMargin">
        <number>2</number>
       </property>
       <property name="rightMargin">
        <number>2</number>
       </property>
       <property name="bottomMargin">
        <number>2</number>
       </property>
       <item>
        <layout class="QHBoxLayout" name="horizontalLayout_4" stretch="2,1,2">
         <item>
          <layout class="QVBoxLayout" name="verticalLayout_2">
           <property name="spacing">
            <number>0</number>
           </property>
           <item>
            <widget class="QLabel" name="label">
             <property name="sizePolicy">
              <sizepolicy hsizetype="Preferred" vsizetype="Maximum">
               <horstretch>0</horstretch>
               <verstretch>0</verstretch>
              </sizepolicy>
             </property>
             <property name="text">
              <string>Time between two qTimerSlot() calls; 
     QTimer-&gt;start(2)</string>
             </property>
             <property name="alignment">
              <set>Qt::AlignCenter</set>
             </property>
             <property name="wordWrap">
              <bool>true</bool>
             </property>
            </widget>
           </item>
           <item>
            <widget class="QGroupBox" name="groupBox_3">
             <property name="font">
              <font>
               <pointsize>16</pointsize>
              </font>
             </property>
             <property name="title">
              <string> max </string>
             </property>
             <property name="alignment">
              <set>Qt::AlignCenter</set>
             </property>
             <layout class="QVBoxLayout" name="verticalLayout_23">
              <property name="spacing">
               <number>0</number>
              </property>
              <property name="leftMargin">
               <number>0</number>
              </property>
              <property name="topMargin">
               <number>0</number>
              </property>
              <property name="rightMargin">
               <number>0</number>
              </property>
              <property name="bottomMargin">
               <number>0</number>
              </property>
              <item>
               <widget class="QLCDNumber" name="lcd_qtimer_max">
                <property name="font">
                 <font>
                  <pointsize>8</pointsize>
                  <weight>50</weight>
                  <bold>false</bold>
                 </font>
                </property>
                <property name="styleSheet">
                 <string notr="true">background-color: rgb(255, 255, 255);</string>
                </property>
                <property name="frameShape">
                 <enum>QFrame::Panel</enum>
                </property>
                <property name="frameShadow">
                 <enum>QFrame::Sunken</enum>
                </property>
                <property name="midLineWidth">
                 <number>1</number>
                </property>
                <property name="smallDecimalPoint">
                 <bool>true</bool>
                </property>
                <property name="digitCount">
                 <number>7</number>
                </property>
                <property name="segmentStyle">
                 <enum>QLCDNumber::Flat</enum>
                </property>
               </widget>
              </item>
             </layout>
            </widget>
           </item>
           <item>
            <widget class="QGroupBox" name="groupBox_2">
             <property name="font">
              <font>
               <pointsize>16</pointsize>
              </font>
             </property>
             <property name="title">
              <string> avg</string>
             </property>
             <property name="alignment">
              <set>Qt::AlignCenter</set>
             </property>
             <layout class="QVBoxLayout" name="verticalLayout_22">
              <property name="spacing">
               <number>0</number>
              </property>
              <property name="leftMargin">
               <number>0</number>
              </property>
              <property name="topMargin">
               <number>0</number>
              </property>
              <property name="rightMargin">
               <number>0</number>
              </property>
              <property name="bottomMargin">
               <number>0</number>
              </property>
              <item>
               <widget class="QLCDNumber" name="lcd_qtimer_avg">
                <property name="font">
                 <font>
                  <pointsize>8</pointsize>
                  <weight>50</weight>
                  <bold>false</bold>
                 </font>
                </property>
                <property name="styleSheet">
                 <string notr="true">background-color: rgb(255, 255, 255);</string>
                </property>
                <property name="frameShape">
                 <enum>QFrame::Panel</enum>
                </property>
                <property name="frameShadow">
                 <enum>QFrame::Sunken</enum>
                </property>
                <property name="midLineWidth">
                 <number>1</number>
                </property>
                <property name="smallDecimalPoint">
                 <bool>true</bool>
                </property>
                <property name="digitCount">
                 <number>7</number>
                </property>
                <property name="segmentStyle">
                 <enum>QLCDNumber::Flat</enum>
                </property>
               </widget>
              </item>
             </layout>
            </widget>
           </item>
           <item>
            <widget class="QGroupBox" name="groupBox">
             <property name="font">
              <font>
               <pointsize>16</pointsize>
              </font>
             </property>
             <property name="title">
              <string> min</string>
             </property>
             <property name="alignment">
              <set>Qt::AlignCenter</set>
             </property>
             <layout class="QVBoxLayout" name="verticalLayout_21">
              <property name="spacing">
               <number>0</number>
              </property>
              <property name="leftMargin">
               <number>0</number>
              </property>
              <property name="topMargin">
               <number>0</number>
              </property>
              <property name="rightMargin">
               <number>0</number>
              </property>
              <property name="bottomMargin">
               <number>0</number>
              </property>
              <item>
               <widget class="QLCDNumber" name="lcd_qtimer_min">
                <property name="font">
                 <font>
                  <pointsize>8</pointsize>
                  <weight>50</weight>
                  <bold>false</bold>
                 </font>
                </property>
                <property name="styleSheet">
                 <string notr="true">background-color: rgb(255, 255, 255);</string>
                </property>
                <property name="frameShape">
                 <enum>QFrame::Panel</enum>
                </property>
                <property name="frameShadow">
                 <enum>QFrame::Sunken</enum>
                </property>
                <property name="midLineWidth">
                 <number>1</number>
                </property>
                <property name="smallDecimalPoint">
                 <bool>true</bool>
                </property>
                <property name="digitCount">
                 <number>7</number>
                </property>
                <property name="segmentStyle">
                 <enum>QLCDNumber::Flat</enum>
                </property>
               </widget>
              </item>
             </layout>
            </widget>
           </item>
          </layout>
         </item>
         <item>
          <widget class="QDial" name="dial">
           <property name="enabled">
            <bool>false</bool>
           </property>
           <property name="minimumSize">
            <size>
             <width>200</width>
             <height>200</height>
            </size>
           </property>
           <property name="minimum">
            <number>-100</number>
           </property>
           <property name="maximum">
            <number>100</number>
           </property>
           <property name="tracking">
            <bool>false</bool>
           </property>
          </widget>
         </item>
         <item>
          <layout class="QVBoxLayout" name="verticalLayout_3">
           <property name="spacing">
            <number>0</number>
           </property>
           <item>
            <widget class="QLabel" name="label_2">
             <property name="sizePolicy">
              <sizepolicy hsizetype="Preferred" vsizetype="Maximum">
               <horstretch>0</horstretch>
               <verstretch>0</verstretch>
              </sizepolicy>
             </property>
             <property name="text">
              <string>Time between two timerEvent() calls; 
     QWidget-&gt;startTimer(50)</string>
             </property>
             <property name="alignment">
              <set>Qt::AlignCenter</set>
             </property>
            </widget>
           </item>
           <item>
            <widget class="QGroupBox" name="groupBox_4">
             <property name="font">
              <font>
               <pointsize>16</pointsize>
              </font>
             </property>
             <property name="title">
              <string> max </string>
             </property>
             <property name="alignment">
              <set>Qt::AlignCenter</set>
             </property>
             <layout class="QVBoxLayout" name="verticalLayout_24">
              <property name="spacing">
               <number>0</number>
              </property>
              <property name="leftMargin">
               <number>0</number>
              </property>
              <property name="topMargin">
               <number>0</number>
              </property>
              <property name="rightMargin">
               <number>0</number>
              </property>
              <property name="bottomMargin">
               <number>0</number>
              </property>
              <item>
               <widget class="QLCDNumber" name="lcd_timer_event_max">
                <property name="font">
                 <font>
                  <pointsize>8</pointsize>
                  <weight>50</weight>
                  <bold>false</bold>
                 </font>
                </property>
                <property name="styleSheet">
                 <string notr="true">background-color: rgb(255, 255, 255);</string>
                </property>
                <property name="frameShape">
                 <enum>QFrame::Panel</enum>
                </property>
                <property name="frameShadow">
                 <enum>QFrame::Sunken</enum>
                </property>
                <property name="midLineWidth">
                 <number>1</number>
                </property>
                <property name="smallDecimalPoint">
                 <bool>true</bool>
                </property>
                <property name="digitCount">
                 <number>7</number>
                </property>
                <property name="segmentStyle">
                 <enum>QLCDNumber::Flat</enum>
                </property>
               </widget>
              </item>
             </layout>
            </widget>
           </item>
           <item>
            <widget class="QGroupBox" name="groupBox_5">
             <property name="font">
              <font>
               <pointsize>16</pointsize>
              </font>
             </property>
             <property name="title">
              <string> avg</string>
             </property>
             <property name="alignment">
              <set>Qt::AlignCenter</set>
             </property>
             <layout class="QVBoxLayout" name="verticalLayout_25">
              <property name="spacing">
               <number>0</number>
              </property>
              <property name="leftMargin">
               <number>0</number>
              </property>
              <property name="topMargin">
               <number>0</number>
              </property>
              <property name="rightMargin">
               <number>0</number>
              </property>
              <property name="bottomMargin">
               <number>0</number>
              </property>
              <item>
               <widget class="QLCDNumber" name="lcd_timer_event_avg">
                <property name="font">
                 <font>
                  <pointsize>8</pointsize>
                  <weight>50</weight>
                  <bold>false</bold>
                 </font>
                </property>
                <property name="styleSheet">
                 <string notr="true">background-color: rgb(255, 255, 255);</string>
                </property>
                <property name="frameShape">
                 <enum>QFrame::Panel</enum>
                </property>
                <property name="frameShadow">
                 <enum>QFrame::Sunken</enum>
                </property>
                <property name="midLineWidth">
                 <number>1</number>
                </property>
                <property name="smallDecimalPoint">
                 <bool>true</bool>
                </property>
                <property name="digitCount">
                 <number>7</number>
                </property>
                <property name="segmentStyle">
                 <enum>QLCDNumber::Flat</enum>
                </property>
               </widget>
              </item>
             </layout>
            </widget>
           </item>
           <item>
            <widget class="QGroupBox" name="groupBox_6">
             <property name="font">
              <font>
               <pointsize>16</pointsize>
              </font>
             </property>
             <property name="title">
              <string> min</string>
             </property>
             <property name="alignment">
              <set>Qt::AlignCenter</set>
             </property>
             <layout class="QVBoxLayout" name="verticalLayout_26">
              <property name="spacing">
               <number>0</number>
              </property>
              <property name="leftMargin">
               <number>0</number>
              </property>
              <property name="topMargin">
               <number>0</number>
              </property>
              <property name="rightMargin">
               <number>0</number>
              </property>
              <property name="bottomMargin">
               <number>0</number>
              </property>
              <item>
               <widget class="QLCDNumber" name="lcd_timer_event_min">
                <property name="font">
                 <font>
                  <pointsize>8</pointsize>
                  <weight>50</weight>
                  <bold>false</bold>
                 </font>
                </property>
                <property name="styleSheet">
                 <string notr="true">background-color: rgb(255, 255, 255);</string>
                </property>
                <property name="frameShape">
                 <enum>QFrame::Panel</enum>
                </property>
                <property name="frameShadow">
                 <enum>QFrame::Sunken</enum>
                </property>
                <property name="midLineWidth">
                 <number>1</number>
                </property>
                <property name="smallDecimalPoint">
                 <bool>true</bool>
                </property>
                <property name="digitCount">
                 <number>7</number>
                </property>
                <property name="segmentStyle">
                 <enum>QLCDNumber::Flat</enum>
                </property>
               </widget>
              </item>
             </layout>
            </widget>
           </item>
          </layout>
         </item>
        </layout>
       </item>
      </layout>
     </widget>
     <resources/>
     <connections/>
    </ui>
    
    


  • indeed strange, shouldn't you also ask "why is this behaviour different in msvc15 and msvc17? After all it is windoze, which historically doesn't have the best task scheduler algorithms on the planet. I would hypothesize that this behaviour is specific to windoze.



  • nice use of lambdas, by the way.


  • Lifetime Qt Champion

    @franto You could try with Qt 5.12.1
    Also, you can check Qt bug tracker to see whether this is a known issue.



  • @Kent-Dorfman
    "shouldn't you also ask "why is this behaviour different in msvc15 and msvc17?"
    I thought ab that, not sure

    "nice use of lambdas, by the way."
    c++(11) is a beast

    @jsulm
    "You could try with Qt 5.12.1"
    I could, need to install it. I hoped someone with 5.12.1(and other versions) would confirm this within few seconds after I added the question.

    "Also, you can check Qt bug tracker to see whether this is a known issue."
    I've just did. My search was unsuccessful ie nothing similar to this post.


Log in to reply