VU Bargraph in QML - High consumption of CPU
-
Hi!
I am writing an application with sixteen VU Bargrah like a VU in audio equipment, with C++ updating the state (turned on or off) of each element (LED) of each VU in QML. The refresh rate is 30 ms for each VU. Everything is working fine, but my application is consuming around 30% of the CPU (a Core 2 DUO - 2.8 GHz with Debian 6). I think I'm doing something wrong.
This is a part of code of my VU in QML:
@
Column {
spacing: intervalLedsRepeater { model: numLeds Rectangle { id: vuLed objectName: "vuLed" width: widthLed height: heightLed border.width: 1 color: "gray" } }
}
@Actually, I am changing the color property of each rectangle, with represent each LED of the VU bargraph, from gray to green.
From C++, I am accessing each element of my VU in this way:
@
vuLeftLeds = vuLeft->findChildren<QObject *>("vuLed");
@and changing the element color in this way:
@
vuLeftLeds.at(i)->setProperty("color", "green");
@I am using the raster graphics system. I trying with opengl, following a documentation from QML performance, but the CPU consumption in this way is greater the with raster, around 60%.
Please, someone can help me with the problem of the CPU consumption or have a better idea to implement a VU bargraph in QML?
Thank you very much!
-
Well, using findChildren is all but optimal. Every time you call this method, your whole QObject tree is parsed to find all children that match this name. Every single object you have in the subtree is checked. Because of this, every time you want to update the screen you inspect your whole object tree causing heavy CPU consumption.
You should create a specific data structure using a container like QVector to store pointers to the right objects or store/cache the list returned by the findChildren call. Then you can iterate quickly on this list of well-known objects, without having to find them each time.You can use valgrind to check where your program actually spends time but I am pretty sure your bottleneck will be in findChildren.
-
I would try to leverage the declarative nature of QML a bit more. Why don't you just export a property to your QML with the value to respond to for each of the columns in your graph, and then set the colors using something like this:
@
Column {
spacing: intervalLedsRepeater {
model: numLedsRectangle { id: vuLed objectName: "vuLed" width: widthLed height: heightLed border.width: 1 color: vuValues.column1Value > maxValue/index ? "green" : "grey" }
}
}
@Now, all you need to do in C++ is to change the value of the column1Value property, and your items will color themselves without you iterating over them.
Note that I did not test the code above.
-
Hi!
rcari, vuLeftLeds is a QList, and the findChildren method is called just once.
This line:
@
vuLeftLeds.at(i)->setProperty("color", "green");
@is called every time that I need to update the VU value, but I did a lot of tests and this doesn't consume CPU time. If I set the same colors to the LEDs in VU every time, the CPU consumption is very low.
Andre, thank you for suggestion. I tried, but the CPU consumption is the same with your solution (actually a lit bit more).
Apparently, the CPU consumption is because the QML changing the colors of the LEDs of the VU. Is this normal?
Can you imagine another way? Maybe changing the opacity of two bars, maybe changing a picture from gray to green.
Why with opengl the CPU consumption is higher?
Please, if someone has a solution, I would be grateful.
Thanks!
1-
-
Just out of curiosity, I tried this way:
@
Column {
spacing: intervalLedsRepeater { model: numLeds Image { id: vuLed objectName: "vuLed" width: widthLed height: heightLed source: ((valueRMS <= index) || (valuePeak == index)) ? "./images/green_led.png" : "./images/gray_led.png" } }
}
@but the performance was worse.
Someone has a source code example of an application with the whole GUI with QML and opengl?