Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. Optimising data process for multiple QML plots
Forum Updated to NodeBB v4.3 + New Features

Optimising data process for multiple QML plots

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
4 Posts 2 Posters 543 Views 1 Watching
  • 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.
  • J Offline
    J Offline
    jars121
    wrote on last edited by
    #1

    I'm building a demonstration application for my device, which essentially uses a pre-recorded data stream (read into memory from a .csv file on program start) to populate the GUI. I've primarily used my desktop during the development and testing of this demonstration, which hasn't had any issues with performance whatsoever. I'm now looking to deploy the solution to my embedded device, and I'm having issues with performance. This wasn't unexpected, as my desktop has 24 logical cores and a current generation GPU, but I've done my best to follow best practise when it comes to designing/writing for embedded application.

    I have several QML files which are loaded into a main QML file. Some of the QML files make use of only basic shapes, text and colour overlays; these QML files running perfectly on the embedded device. One of the QML files is a series of plots however, which is where I'm having some issues. The file has 12 BarSeries plots and 4 LineSeries plots. Importantly, each BarSeries plot only shows a single value at a time. I.e. just a vertical bar which changes height on each data point change.

    The LineSeries plots each have 200 points, but I've tried varying this value from 50 - 600 with seemingly little impact. OpenGL is enabled on all plots.

    What I've tried:

    • Initially I had a QML timer which would trigger a c++ update function at 60Hz for the LineSeries plots only. The BarSeries plots (i.e. the BarSet within each BarSeries) was updated via a signal-slot connection to c++. I figured this wasn't optimal as the timer was running on the main UI thread, so I removed it.
    • I replaced the QML timer with a Connections function in QML, one for each LineSeries plot, which would update the LineSeries data when the corresponding c++ signal was emitted. I dropped the refresh rate of the LineSeries signals considerably, but this didn't seem to make much difference. I was getting well under 1Hz update across the whole GUI (more like one screen update every ~5 seconds), so changing the emit frequency from 60Hz to 2Hz (for example) obviously didn't make any difference.

    With the above point in mind, I must be missing something here. The main c++ function (which is on a different thread to the UI/QML thread) executes very quickly, which I've tested on both my desktop and the embedded device. I use counters to artificially execute the function at 60Hz which works nicely. However, if the QML rendering side of the equation is taking longer than the ~16ms (60Hz) between c++ function executions, perhaps the UI is locking up because it's being bombarded with signals at a rate faster than it's capable of rendering.

    I've used the QML Profiler in QtCreator but nothing stands out as being the cause. So here are my initial questions:

    1. How is the QML rendering actually completed? If I have these 12 BarSeries plots, 4 LineSeries plots and another 12 images, each with a color overlay, all being updated by their own c++ signal, are these all aggregated into the one QML render/update?
    2. Depending on the answer to 1 above, would there be any benefit in aggregating all the plot (both Bar and Line) data into a single container (perhaps a QAbstractTableModel) so that a single signal can be sent from c++?

    If there really isn't much to be gained from trying the above, I'd be happy to accept that I'm beyond the capability of my embedded hardware and redesign this particular QML file accordingly, but I wanted to make absolutely certain before doing so.

    1 Reply Last reply
    0
    • GrecKoG Offline
      GrecKoG Offline
      GrecKo
      Qt Champions 2018
      wrote on last edited by
      #2

      How do you update your plots?

      Have you tried updating your data with a QAbstractItemModel and using that with a VXYModelMapper?

      1 Reply Last reply
      0
      • J Offline
        J Offline
        jars121
        wrote on last edited by
        #3

        Hi Grecko,

        I haven't tried QAbstractItemModel, I think that's probably the next step. At the moment I update the plots as follows:

        BarSeries:

        In QML, each BarSeries plot has the following basic structure.

        ChartView {
            id: chartViewPlot1
            //Anchoring, margins, etc.
        
            ValueAxis {
                id: axisX1
                color: "red"
            }
        
            ValueAxis {
                id: axisY1
                min: 0
                max: 100
                //Other parameters
            }
        
            BarSeries {
                id: barSeries1
                useOpenGL: true
                axisX: axisX1
                axisY: axisY1
        
                BarSet {
                    values: myClass.barValues[0] ? [myClass.barValues[0]] : []
                }
        }
        

        In my myClass c++ file, I have a QVariantList barValues which is continuously updated in the 60Hz c++ function. At the end of the 60Hz c++ function I emit the barValuesChanged signal, which causes QML to update the BarSet value. This is the approach I use for all the BarSeries plots.

        As for the LineSeries, I've played with a couple of methods. Firstly I had a timer in QML which would call a function in my myClass c++ file.

        QML:

        Timer {
            interval: (1 / 60) * 1000
            running: true
            repeat: true
            onTriggered: {
                myClass.update1(lineSeries1)
            }
        }
        

        myClass.cpp:

        void myClass::update1(QtCharts::QAbstractSeries *lineSeries1) {
            if (lineSeries1) {
                QtCharts::QXYSeries *xySeries = static_cast<QtCharts::QXYSeries *>(lineSeries1);
        
                xySeries->replace(m_lineSeries1);
            }
        }
        

        In this approach I'd replace the full set of data on each update. I've also played with appending each new data point and removing the first data point, so that the size of LineSeries remains the same. As I've got 4 LineSeries plots, I initially had 4 myClass::update[1, 2, 3, 4] functions, which I then consolidated to a single function. However, I'm still unsure about this approach as each LineSeries' data is replace()'d individually/sequentially. This is why I'm wondering whether something like a QAbstractItemModel might be better, as I might be able to update/repaint all the plots in fewer clock cycles?

        1 Reply Last reply
        0
        • GrecKoG Offline
          GrecKoG Offline
          GrecKo
          Qt Champions 2018
          wrote on last edited by
          #4

          Yeah I guess using a model would allow updates to be done incrementally instead of replacing every data points.

          Not sure it will solve your problem but it will at least be better.

          1 Reply Last reply
          0

          • Login

          • Login or register to search.
          • First post
            Last post
          0
          • Categories
          • Recent
          • Tags
          • Popular
          • Users
          • Groups
          • Search
          • Get Qt Extensions
          • Unsolved