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-74345Hi,
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:
This one shows 'avg' time with cursor movement. In case of QTimer period of slot calls rises from 2ms to nearly 5ms.
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
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->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->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.
-
@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.