Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    QElapsedTimer and QTimer strange behavior

    General and Desktop
    3
    3
    3152
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • LabanK
      LabanK last edited by

      Currently working on a project we face the following strange behavior:
      We set up a QTimer timing out each 5ms.
      We also use a QElapsedTimer measuring the time at each QTimer timeout.
      The printouts show a relative stable loop time.

      However, after exactly (!) 3497 iterations, the loop time is 4 milliseconds. This happens at exactly iteration 3497 each time the program is run, and with a cyclic behavior (it=6994, 10491, ...). The iteration may vary between computers, but occurs around that iteration (~3500).

      Either the QTimer times out too soon (at that iteration) or the time measurement (QElapsedTimer) does something strange. Could that be a quantification error? We have also checked against system time (QDateTime) and windows QueryPerformanceTimers.

      This phenomena occurs on Windows 7 64-bit only; on Linux OpenSUSE we do not see the same. We tried both Qt-4.8 and Qt-5.0 versions.

      Debug printouts:

      @"Iteration: 3495, Nanosecs: 17470502465, ns diff: 4992721, Millisecs: 17470.5, ms diff: 5.0, systime: 1372419103724"
      "Iteration: 3496, Nanosecs: 17475514952, ns diff: 5012487, Millisecs: 17475.5, ms diff: 5.0, systime: 1372419103729"
      "Iteration: 3497, Nanosecs: 17479511409, ns diff: 3996457, Millisecs: 17479.5, ms diff: 4.0, systime: 1372419103733"
      "Iteration: 3498, Nanosecs: 17484515153, ns diff: 5003744, Millisecs: 17484.5, ms diff: 5.0, systime: 1372419103738"
      "Iteration: 3499, Nanosecs: 17489533341, ns diff: 5018188, Millisecs: 17489.5, ms diff: 5.0, systime: 1372419103743" @

      Example code:

      main.cpp
      @#include <QCoreApplication>
      #include "timertester.hpp"

      int main(int argc, char *argv[])
      {
      QCoreApplication a(argc, argv);
      TimerTester time_test;
      time_test.start();
      return a.exec();
      }
      @

      timertester.hpp
      @
      #ifndef TIMERTESTER_HPP
      #define TIMERTESTER_HPP

      #include <QtCore>

      class TimerTester : public QObject
      {
      Q_OBJECT
      public:
      explicit TimerTester(QObject* parent = 0);
      void start();

      signals:

      public slots:
      void tic();

      private:
      QTimer* m_timer;
      QElapsedTimer m_elapsed_timer;

      qint32 m_iteration;
      qint64 m_base_nsec;
      qint64 m_prev_nsec;
      };

      #endif // TIMERTESTER_HPP
      @

      timertester.cpp
      @#include "timertester.hpp"

      TimerTester::TimerTester(QObject* parent) : QObject(parent)
      {
      m_timer = new QTimer(this);
      m_timer->setInterval(5);
      connect(m_timer, SIGNAL(timeout()), this, SLOT(tic()));

      m_iteration = 0;
      m_base_nsec = 0;
      m_prev_nsec = 0;
      }

      void TimerTester::start() {
      m_elapsed_timer.start();
      m_timer->start();
      }

      void TimerTester::tic() {
      //First operation, store total number of nano seconds elapsed when
      //QTimer times out
      qint64 nsecs_elapsed = m_elapsed_timer.nsecsElapsed();
      qint64 sys_time = QDateTime::currentMSecsSinceEpoch();

      //Adjust elapsed nano seconds with base line
      if(m_base_nsec == 0) {
      m_base_nsec = nsecs_elapsed;
      }
      nsecs_elapsed -= m_base_nsec;

      //Nano seconds since last QTimer time out
      //Around 5 millions if no timer slips
      qint64 nsec_diff = nsecs_elapsed - m_prev_nsec;
      m_prev_nsec = nsecs_elapsed;

      //Also present in micro seconds
      double msecs = double(nsecs_elapsed) / 1e6;
      double msec_diff = double(nsec_diff) / 1e6;
      m_iteration++;

      //Printout
      qDebug() << QString("Iteration:%1, Nanosecs:%2, ns diff:%3, Millisecs:%4, ms diff:%5, systime: %6").
      arg(m_iteration, 5).
      arg(nsecs_elapsed, 12).
      arg(nsec_diff, 8).
      arg(msecs, 8, 'f', 1).
      arg(msec_diff, 4, 'f', 1).
      arg(sys_time);
      }
      @

      1 Reply Last reply Reply Quote 0
      • JKSH
        JKSH Moderators last edited by

        Windows is a non-deterministic OS, so keeping strict time isn't a high priority for it. I'm surprised you managed to get 5 ms most of the time, actually -- Windows' system timer has a resolution of somewhere between "10ms -- 16ms":http://msdn.microsoft.com/en-us/library/windows/desktop/ms725496(v=vs.85).aspx Windows does provide "multimedia timers" that are much more precise, but I doubt QTimer uses that.

        In contrast, Linux kernels provide timers of 1ms resolution, which makes Linux QTimers ~10x more precise than their Windows counterparts.

        The periodicity of your anomalies is interesting -- I'm curious to know what causes it!

        Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

        1 Reply Last reply Reply Quote 0
        • S
          suswak last edited by

          [quote author="JKSH" date="1372434688"]Windows does provide "multimedia timers" that are much more precise, but I doubt QTimer uses that.[/quote]

          Hi. I actually found some information posted by Netich on other forums that Qt indeed uses multimedia timers. In the Qt's 4.6.0 change-log on line 111 it states:

          " - QEventDispatcherWin32 (internal class)
          * Changed the threshold for using multimedia timers to 20ms (was 10ms)."

          1 Reply Last reply Reply Quote 0
          • First post
            Last post