QCustomPlot Discussion and Comments

QCPColorMap replot performanceReturn to overview

I'm working on plotting some large 2D data arrays with QCPColorMap in a semi-realtime display application (roughly 1 Hz replot rate). For arrays roughly 1kx1k in size the performance is quite good with a replot time on the order of 20ms. Unsurprisingly this scales up as the array increases in size and when I hit a size of 4kx4k the replot time reaches something closer to ~230ms. So I'm able to display data at this size but the issue is that it makes the GUI non-responsive during this replot time which is long enough for it to be very obvious when using the GUI. I allow for plot inspection while the updates are occurring as this is kind of a live inspection tool. Sometimes I even have to display and inspect larger arrays and the replot times become quite large as the data size goes above 4kx4k.

So, I'm hoping to find any suggestions on whether or not it is possible to improve the replot time for such large arrays. If it can get to under 100ms that would be a large improvement in tool usability. Obviously this is really pushing on the performance with such large data arrays...

I have pasted an example below which is derived from the benchmark.cpp program in the QCustomPlot git repository (https://gitlab.com/DerManu/QCustomPlot/-/blob/master/tests/benchmark/benchmark.cpp).
Here's what I have tried so far:
* I have attempted to set all of the notantialiasing steps as directed in the plot performance advice page.
* I have attempted opengl which was actually slower than without opengl.
* I have attempted only replotting the colormap layer which does not change performance.

This is all done with QT 6.3.1 on a windows machine with MSVC 2019 compiler with the build configuration set to "release." Any advice would be greatly appreciated. I can post the entire project on github or similar if that makes anything easier.

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    map = new QCPColorMap(ui->mPlot->xAxis, ui->mPlot->yAxis);

    int bits = 12;
    int px = 1 << bits;

    map->data()->setSize(px, px);
    map->data()->setRange(QCPRange(0, px - 1), QCPRange(0, px - 1));
    std::srand(0);
    for (int x=0; x<map->data()->keySize(); ++x)
    {
      for (int y=0; y<map->data()->valueSize(); ++y)
      {
        map->data()->setCell(x, y, std::rand()/double(RAND_MAX));
        //map->data()->setCell(x, y, 0.0);
      }
    }
    //map->data()->fill(10.0);

    QCPColorGradient gradient(QCPColorGradient::gpHot);
    map->setGradient(gradient);
    map->setInterpolate(false);
    map->rescaleDataRange();
    ui->mPlot->rescaleAxes();

    // Attempt any performance improvements
    // https://www.qcustomplot.com/documentation/performanceimprovement.html
    ui->mPlot->setNotAntialiasedElements(QCP::aeAll);
    ui->mPlot->setNoAntialiasingOnDrag(true);
    ui->mPlot->setPlottingHints(QCP::phFastPolylines);

    // try layer.
    //ui->mPlot->addLayer("image", ui->mPlot->layer("main"), QCustomPlot::limAbove);
    //ui->mPlot->layer("image")->setMode(QCPLayer::lmBuffered);
    //map->setLayer("image");

    // do once...
    map->data()->setCell(0, 0, 0); // to invalidate the currently cached map image
    ui->mPlot->replot();

    // Set up a timer for 1 Hz replots
    timer = new QTimer();
    timer->setInterval(1000);

    connect(timer, SIGNAL(timeout()), this, SLOT(vid_replot()));
    timer->start();
}

MainWindow::~MainWindow()
{
    delete ui;
}

// 1 Hz replot function
void MainWindow::vid_replot(void)
{
    //QElapsedTimer timer;
    //timer.start();
    map->data()->setCell(0, 0, 0); // to invalidate the currently cached map image
    ui->mPlot->replot(QCustomPlot::rpQueuedReplot);
    //ui->mPlot->layer("image")->replot();
    qDebug() << ui->mPlot->replotTime();
    //qDebug() << timer.elapsed();
}

> * I have attempted opengl which was actually slower than without opengl.

Let me correct this statement: opengl is faster, but only marginally, with a replot time of about 200ms for a 4kx4k data array.