QCustomPlot Discussion and Comments

Performance of Realtime GraphReturn to overview

Hi,
I have a realtime chart along with other objects like rectangles and other shapes.
I receive the data via web-sockets, and on receiving the data I update the chart and the rectangles as well.
Frequency of receiving the data is every second. So every second I receive data and I update the chart and objects accordingly.

My websocket is running on a QThread and on receiving the data ->> I do the calculations and I send a signal to the main thread to render.So practically it renders every second.

The mechanism how I am updating?

Line Chart- On receiving the data I am simply calling

addData
on the graph and adding the delta.
Rectangles-> I am creating 600-700 rectangles every second and asking the application to render.

Since qcustomplot is more like a canvas, for every render it destroys all the items and renders the again, therefore I am recreating the rectangles every second.

There is about 8-9 hours of line chart data . Also there are about 500-700 rectangles on the screen.

The problem is the application is hanging/the mouse pointer is stuck and the rendering is not so real time as the window of the application is stuck as well.

My question

Am I doing the right way to update?
Why is my application hanging? Is the data too much for the UI to render?

Note- I am using a macbook pro, which has plenty of cores of computing power, so I guess my hardware capability is not an issue here.

Hello Soum,

Can you please explain what data type you are inserting into the graph? Are you inserting point by point or a list/vector? Do your rectangles have a color fill? What is the connection type of your thread signal-slot?

Can you please explain what data type you are inserting into the graph?

void MainWindow::appendDataToTickChart(double time, double ltp) {
    ui->chartPlot->graph(0)->addData(time, ltp);
}

Here time is epoch but double as datatype->for example 1521866337.0 and ltp can be 230.30.

Are you inserting point by point or a list/vector?
Its purely point...For the first time I insert a vector.Here is the code for the first time creation.

void commonrenderer::firstTimeAddData(QCustomPlot *obj,plotObject *timeToLtp,double *lowest_x,double *highest_x,double *lowest_y,double *highest_y){
    obj->clearGraphs();
    obj->xAxis->setRange(*lowest_x,*highest_x);
    obj->yAxis->setRange(*lowest_y,*highest_y);

    obj->addGraph();
    obj->graph(0)->setPen(commonObj.tickColor);
    obj->graph(0)->setData(QVector<double>::fromStdVector(*(timeToLtp->getXAxisValues())), QVector<double>::fromStdVector(*(timeToLtp->getYAxisValues())));

}

Do your rectangles have a color fill?

Yes they do have color fills..The creation of the rectangles have this piece of code.

void commonrenderer::createRectangle(QCustomPlot *obj,unsigned int *x1, double *y1, unsigned int *x2,
                                     double *y2, double *numberWhichWouldLighten,QColor *baseColor) {
    //numberWhichWouldLighten ->>>>>>>> 100 is white and 1 is black
    if (*numberWhichWouldLighten > 1) {
        //qDebug()<<"rect="<<y1<<"-"<<x1<<"-"<<x2;

        QCPItemRect* rect = new QCPItemRect(obj);
        rect->topLeft->setCoords(*x1, *y1);
        rect->bottomRight->setCoords(*x2, *y2);
        rect->setBrush(QBrush((*baseColor).lighter(*numberWhichWouldLighten)));
        rect->setPen(Qt::NoPen);
    }
}

What is the connection type of your thread signal-slot?

Well I consider myself very naive in QT so maybe I donot get this question.
This is how I do the subscription

void MainWindow::subscribeToEvents() {
    qDebug() << "Websocket Thread Started..subscribing to events";
    connect(ui->button_startWs, SIGNAL(clicked()), this,
            SLOT(onStartWebsocketButtonClicked()));
    connect(this, SIGNAL(startConnection(QString,QString,bool)), websocketObj,
            SLOT(startConnection(QString,QString,bool)));
    connect(ui->button_stopWs, SIGNAL(clicked()), websocketObj,
            SLOT(stopConnection()));
    connect(livecalculationObj, SIGNAL(renderDelta()), this,
            SLOT(renderDelta()));
    connect(livecalculationObj, SIGNAL(renderFirstTime()), this,
            SLOT(renderFirstTime()));
    connect(websocketObj, SIGNAL(processIncomingMessage(QString)),
            livecalculationObj,
            SLOT(onMessageReceivedFromWebsocketForProcessing(QString)));

}

And to Fire the event I use commands like this
emit renderFirstTime();

@Mirza any help of this?

sounds like your problem is about threading,
related to websocketObj and onMessageReceivedFromWebsocketForProcessing

Though, I know qt can handle that using singal and slot, you better also make sure onMessageReceivedFromWebsocketForProcessing is called in the same thread by printing the thread id.

Try changing your appendDataToTickChart to

void MainWindow::appendDataToTickChart(QCPGraphData &data) {
    ui->chartPlot->graph(0)->addData(data);
}

to initially prepare the data type QCP container wants and potentially lose some overhead.

Other than that everything looks good at first sight. I don't see the thread and object code section, can you try to change your last connect to

connect(websocketObj, SIGNAL(processIncomingMessage(QString)),
            livecalculationObj,
            SLOT(onMessageReceivedFromWebsocketForProcessing(QString)), Qt::QueuedConnection);

Hope it helps