Timer

Analyze out of control timers.

This examples shows GammaRay's capabilities in analyzing timer activity.

Problem

The example application shows two buttons, clicking any one of them is supposed to trigger a deferred repaint of the application using two variations of a single-shot timer. In both cases we however observe 100% CPU load afterwards.

Analyzing the CPU load with a debugger or profiler points to frequently firing timers, but doesn't support us in finding where that timer actually came from.

Investigation

While the target application is running, open the Timers view in GammaRay to obtain a list of all active timers. Sorting by Total Wakeups or Wakeups/Sec allows to quickly identify timers running amok, such as the recurring 0-interval timers in our example.

When working with a debug build, the context menu on the Timers view allows you directly to navigate to the source code of the created timer object, or timer event receiver.

QTimer and QML Timer

When using timer objects such as QTimer or a QML Timer, you can further inspect those by switching to the Object Browser via the context menu in the Timers view. In the object browser the following inspection views are particularly useful for timer objects:

  • The Connections view allows you to inspect to which action the timeout() signal is connected to, which can help to identify the timer if source navigation is not available.
  • The Methods view allows to manually stop timers, to verify a specific timer is the source of a problem, or to observe if it gets erroneously restarted.

In the above example, we notice that the QTimer::singleShot property was accidentally left on false, causing the timer to fire constantly.

auto timer = new QTimer(&w);
QObject::connect(timer, &QTimer::timeout, &w, [&w] { w.repaint(); });
timer->setInterval(0);
// timer->setSingleShot(true);
timer->start();

The Signal Plotter view of GammaRay can provide additional help in finding too frequently triggering timer object, by means of observing their timeout signals.

QTimerEvent

Raw timer events are less commonly used than timer object and provide fewer options for runtime diagnostics unfortunately.

In our example the source of the problem is a missing QObject::killTimer call in the QTimerEvent handler.

void timerEvent(QTimerEvent *event) override
{
    Q_UNUSED(event);
    m_widget->repaint();
    // killTimer(event->timerId());
}

Files: