Sunday, September 19, 2021

Measuring the Frame Rate in Qt/QML

I frequently need to measure the frame rate in a Qt/QML application to have an idea of how heavy the changes I'm making are. In the past, I found two approaches that seemed to answer the question: one is using a simple QML item, measuring the frequency of changes of a property. The other is using a custom QQuickItem, measuring the frequency of the calls received to refresh it. I never used the first approach because it did not feel safe, while I typically used the second.

Instead of copy/pasting code into my projects repeatedly, I thought I could add it to my collection of simple procedures in https://github.com/carlonluca/lqtutils, making it simple to integrate when needed. I therefore asked myself which one to include.

By thinking a bit about it, I thought of a different simpler approach using the signal QQuickWindow::frameSwapped(). This is what Qt doc says about it:

This signal is emitted when a frame has been queued for presenting. With vertical synchronization enabled the signal is emitted at most once per vsync interval in a continuously animating scene. This signal will be emitted from the scene graph rendering thread.

This seemed a reasonable approach, simple to implement, very concise and lightweight. The resulting code is in the repo. Doc is in: https://github.com/carlonluca/lqtutils#lqtutils_uih.

Is this Correct?

I was wondering if my approach was correct, so I thought I could compare with the other approaches. I took the snippets from this SO question. I tried the three techniques separately and also tried to add them together in the same code for a comparison of the values. For the test I used my QML app here: https://github.com/carlonluca/Fall. In the branch https://github.com/carlonluca/Fall/tree/fps_comparison I added all the components to compare. This is the result:


As it can be seen, the method based on the QQuickPaintedItem gives the same result of the one based on the frameSwapped() signal. The other one is very different. The explanation for this is probably based on the fact that the Qt scene graph on Linux renders through the threaded render mode. In fact, forcing a single-threaded render mode makes the three techniques agree on the measurement (second run in the video).

Compared to a custom QQuickPaintedItem, the frameSwapped() technique seems to be more lightweight, so it is the one I implemented in my repo.

Bye! ;-)

No comments:

Post a Comment