Deleting QChart Causes 30+ Second Application Hang!
-
@FleetingMemory
So it should be reproducible with half a million random points across, say, 10 series? I think it keeps them as aQMap
, I'm not sure whether 30 seconds is to be expected for deleting them all, it does sound a bit long. As @JoeCFD says, you might have to thin your plotted points. If you want to investigate further, try creating the line series and then deleting them without even adding them to the chart, is that similar time?@JonB I will try that. I also tried calling remove all series and then adding the new series into the same chart, but that seems to take 5-10 seconds longer than deleting...
Also, I have a way to manipulate the range of the X-Axis, which effectively zooms in, making all points viewable and necessary @JoeCFD
-
@FleetingMemory
So it should be reproducible with half a million random points across, say, 10 series? I think it keeps them as aQMap
, I'm not sure whether 30 seconds is to be expected for deleting them all, it does sound a bit long. As @JoeCFD says, you might have to thin your plotted points. If you want to investigate further, try creating the line series and then deleting them without even adding them to the chart, is that similar time?@JonB I tried storing all the series* in a QMap<int, series*> after building them instead of the chart. I then for-looped the Map and deleted the series* within (as well as the map itself). This deletion process took less than 1 second. So the issue is when clearing/deleting the chart
My computer is running 12/24T Xeon, with 128gb ddr4 memory (so it's not my system....)
Update - If I still attach to the chart and build the QMap above, and then loop through and delete it again takes ~30+ seconds to delete all the series from memory. There seems to be an issue with deleting them after they are added to the QChart...
-
So I have done a little digging. It seems no matter what I do, whether I delete all series or delete the chart, as it deletes, the chart loops through its update/repaint method removing one series at a time. I think these function calls are what is slowing it down. It needs to be updated so that it does not call repaint or loop through update when delete is called. I think this is a bug?
-
So I have done a little digging. It seems no matter what I do, whether I delete all series or delete the chart, as it deletes, the chart loops through its update/repaint method removing one series at a time. I think these function calls are what is slowing it down. It needs to be updated so that it does not call repaint or loop through update when delete is called. I think this is a bug?
@FleetingMemory
Well I don't find anything like you do. Here is a sample I think you should try:#ifndef WIDGET_H #define WIDGET_H #include <QtCharts> #include <QWidget> class Widget : public QWidget { Q_OBJECT public: Widget(QWidget *parent = nullptr); ~Widget(); private: QChart *chart; QChartView *chartView; private slots: void deleteChart(); }; #endif // WIDGET_H
#include <QDebug> #include <QElapsedTimer> #include <QTimer> #include <QVBoxLayout> #include "widget.h" // using namespace QtCharts; Widget::Widget(QWidget *parent) : QWidget(parent) { setGeometry(100, 100, 800, 600); setLayout(new QVBoxLayout); this->chart = new QChart(); this->chartView = new QChartView(chart, this); layout()->addWidget(chartView); chartView->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); for (int i = 0; i < 10; i++) { QLineSeries* series = new QLineSeries(); for (int x = 0; x < 50000; x++) series->append(x, x * (i + 1)); chart->addSeries(series); } QTimer::singleShot(2000, this, &Widget::deleteChart); } void Widget::deleteChart() { QElapsedTimer elapsed; qDebug() << "Starting to delete"; elapsed.start(); layout()->removeWidget(chartView); delete chart; chart = nullptr; delete chartView; chartView = nullptr; qDebug() << "Finished deleting" << elapsed.elapsed(); } Widget::~Widget() {}
500,000 points, 10 series. For me this takes 6 milliseconds to "delete", where you claim 30 seconds! Ubuntu 24.04, VirtualBox slow machine/not nearly as much memory as you, Qt 6.4.2 supplied with Ubuntu. How long does it take you?
Possible it could be slow if compiled for Debug, though that is actually how I ran mine, you might check whether Release makes a huger difference?
-
So I have done a little digging. It seems no matter what I do, whether I delete all series or delete the chart, as it deletes, the chart loops through its update/repaint method removing one series at a time. I think these function calls are what is slowing it down. It needs to be updated so that it does not call repaint or loop through update when delete is called. I think this is a bug?
@FleetingMemory Is it possible to block qchart plotting while series are deleted. Do update of qchart after all series are cleared?
-
@FleetingMemory Is it possible to block qchart plotting while series are deleted. Do update of qchart after all series are cleared?
-
@JoeCFD
If you read OP's first post I am relying that he has tried all this sort of stuff. I just take his first two points and delete the chart view and chart, which he claims is slow.@JonB In his first post, He did
deleting the QChart deleting the QChartView Hiding chart/chartview prior to deleting Removing all series prior to deleting <===he might not have tried to block update of qchart in deletion of series. running QCoreApplication::procesEvents() before/after delete
His issue:
as it deletes, the chart loops through its update/repaint method removing one series at a time.If he is able to block update of qchart while series are deleted, one final update may be ok. I do not use QChart (not free) and am not sure if it is doable.
-
@JonB In his first post, He did
deleting the QChart deleting the QChartView Hiding chart/chartview prior to deleting Removing all series prior to deleting <===he might not have tried to block update of qchart in deletion of series. running QCoreApplication::procesEvents() before/after delete
His issue:
as it deletes, the chart loops through its update/repaint method removing one series at a time.If he is able to block update of qchart while series are deleted, one final update may be ok. I do not use QChart (not free) and am not sure if it is doable.
@JoeCFD
I'm still not with you. The first two lines says he deletes chart and view. I do no more or less than that in my code. It takes 6 milliseconds. He says it takes him 30 seconds. I don't know why or what other than mine he is doing or needs to do? (I checked my code with valgrind, no leaks reported.) -
@JoeCFD
I'm still not with you. The first two lines says he deletes chart and view. I do no more or less than that in my code. It takes 6 milliseconds. He says it takes him 30 seconds. I don't know why or what other than mine he is doing or needs to do? (I checked my code with valgrind, no leaks reported.) -
@JonB Could be hardware related. I think he needs to try your code and see if he still has the same problem. If not, he has other issues in his code.
-
@JoeCFD
I am hoping he will (a) try my code and see the time for him, (b) criticise my code if I have done anything wrong (like a leak) and then (c) compare against whatever else he is doing if different. -
@FleetingMemory
Well I don't find anything like you do. Here is a sample I think you should try:#ifndef WIDGET_H #define WIDGET_H #include <QtCharts> #include <QWidget> class Widget : public QWidget { Q_OBJECT public: Widget(QWidget *parent = nullptr); ~Widget(); private: QChart *chart; QChartView *chartView; private slots: void deleteChart(); }; #endif // WIDGET_H
#include <QDebug> #include <QElapsedTimer> #include <QTimer> #include <QVBoxLayout> #include "widget.h" // using namespace QtCharts; Widget::Widget(QWidget *parent) : QWidget(parent) { setGeometry(100, 100, 800, 600); setLayout(new QVBoxLayout); this->chart = new QChart(); this->chartView = new QChartView(chart, this); layout()->addWidget(chartView); chartView->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); for (int i = 0; i < 10; i++) { QLineSeries* series = new QLineSeries(); for (int x = 0; x < 50000; x++) series->append(x, x * (i + 1)); chart->addSeries(series); } QTimer::singleShot(2000, this, &Widget::deleteChart); } void Widget::deleteChart() { QElapsedTimer elapsed; qDebug() << "Starting to delete"; elapsed.start(); layout()->removeWidget(chartView); delete chart; chart = nullptr; delete chartView; chartView = nullptr; qDebug() << "Finished deleting" << elapsed.elapsed(); } Widget::~Widget() {}
500,000 points, 10 series. For me this takes 6 milliseconds to "delete", where you claim 30 seconds! Ubuntu 24.04, VirtualBox slow machine/not nearly as much memory as you, Qt 6.4.2 supplied with Ubuntu. How long does it take you?
Possible it could be slow if compiled for Debug, though that is actually how I ran mine, you might check whether Release makes a huger difference?
@JonB I think its not the number of points in a singular line, but the number of series (lines) in total causing the problem. My times I listed are from running on release.
-
@JonB I think its not the number of points in a singular line, but the number of series (lines) in total causing the problem. My times I listed are from running on release.
@FleetingMemory
I asked you to produce a minimal example such as mine but you have not. I said earlier I was guessing 10 series to make 500,000 points. If you want help I don't see why you can't convey the necessary information, no point leaving me to create 10 series I mentioned and then say it's not the right number..... And you could always alter my code to whatever numbers you desire to test..... -
@JonB I think its not the number of points in a singular line, but the number of series (lines) in total causing the problem. My times I listed are from running on release.
@FleetingMemory try to call
removeAllSeries() first. It seems this call will not trigger update of qchart.
and then update,
next delete chart. -
@FleetingMemory try to call
removeAllSeries() first. It seems this call will not trigger update of qchart.
and then update,
next delete chart.@JoeCFD Will give this a try and let you know!
-
@JoeCFD Will give this a try and let you know!
@FleetingMemory
In your first post of the steps you have tried you already includedRemoving all series prior to deleting
-
Yeah, I am going to retry in release with elapsed() to see what is going on and give more info.
Query Size 450,000 points. Spread across 12,000 series.
populating the series after query takes 2,964 milliseconds
Gets stuck on remove all series (freezes main thread), takes 35,774 milliseconds to remove -
Yeah, I am going to retry in release with elapsed() to see what is going on and give more info.
Query Size 450,000 points. Spread across 12,000 series.
populating the series after query takes 2,964 milliseconds
Gets stuck on remove all series (freezes main thread), takes 35,774 milliseconds to remove@FleetingMemory
Yes please test. OOI how can you expect to display 12,000 series to a user, I just don't get it?