Own thread for each QQuickWidget
-
Hi,
we are porting a rather big embedded application from Qt4 to Qt5. To benefit from the new features of Qt Quick, we decided to reimplement some dialogs in QML by using QQuickWidgets. Now we have realized that there seems to be an own thread for each QQuickWidget. Because each threads needs its own stack, this cost much memory.
Does anyone have some information about QQuickWidgets and their threads? I could not find anything in the documentation. Is there a way to change this behavior?
Best regards,
stewo -
I have heard about the only one GUI thread topic, but /proc/pid/status shows me a very high number of threads and it increases with each created QQuickWidget. Together with the VmSize. I think those threads are no GUI threads, but perhaps for some interactions between Qt Quick and Qt Widget. Perhaps for the Qml Context or Engine?
Here is some code to reproduce this behavior. Works for me on our embedded target and in Ubuntu.
void MainWindow::on_pushButton_clicked() { QQuickWidget* quickWidget = new QQuickWidget(this); quickWidget->setSource(QUrl("qrc:/RedRectangle.qml")); quickWidget->show(); QProcess process; process.start("cat", QStringList() << QString("/proc/%1/status").arg(QCoreApplication::applicationPid())); process.waitForFinished(); QString output = process.readAll(); qDebug() << "Number of threads:" << output.split("Threads").at(1).split("\n").at(0).mid(2); qDebug() << "VmSize:" << output.split("VmSize").at(1).split("\n").at(0).mid(4); process.close(); }And here the output of this code:
Number of threads: "7" VmSize: "175096 kB" Number of threads: "8" VmSize: "197020 kB" Number of threads: "9" VmSize: "217928 kB" Number of threads: "10" VmSize: "238832 kB"Edit:
I added the VmSize. Each QQuickWidgets reserves about 20 MB of RAM. 8 MB of those are for the stack.Edit:
I looked into the documentation of QQuickWidget and saw that there is a constructor which needs a QQmlEngine. When creating a global engine-object and using this for the QQuickWidgets there are no additional threads and just a bit additional memory usage. I will try to create a global engine and use local contexts for each QQuickWidget in our application. If the application will work as before, this could reduce the memory usage drastically.Edit:
I finally found a solution. The problem was to find a way to pass an own QQmlContext to a QQuickWidget, but use the same QQmlEngine at the same time. I had to take the indirection over the QQmlComponent. Here is some code:QQmlEngine* engine = new QQmlEngine(); QQmlContext* context = new QQmlContext(engine); engine->rootContext()->setContextProperty("message", "marco"); context->setContextProperty("message", "polo"); QQuickWidget* quickWidget = new QQuickWidget(engine, this); quickWidget->setResizeMode(QQuickWidget::SizeRootObjectToView); QQmlComponent* component = new QQmlComponent(engine, "qrc:/MarcoPolo.qml"); quickWidget->setContent(component->url(), component, component->create(context)); ui->verticalLayout->addWidget(quickWidget);This reduced the virtual memory usage and the number of threads drastically.
Please tell me, if anyone has a simpler solution.
-
UI only in main thread and rest of the backend work can be in worker thread.
-
Hi,
we are porting a rather big embedded application from Qt4 to Qt5. To benefit from the new features of Qt Quick, we decided to reimplement some dialogs in QML by using QQuickWidgets. Now we have realized that there seems to be an own thread for each QQuickWidget. Because each threads needs its own stack, this cost much memory.
Does anyone have some information about QQuickWidgets and their threads? I could not find anything in the documentation. Is there a way to change this behavior?
Best regards,
stewo@stewo said in Own thread for each QQuickWidget:
Now we have realized that there seems to be an own thread for each QQuickWidget
how exactly did you get to that conclusion?
-
I have heard about the only one GUI thread topic, but /proc/pid/status shows me a very high number of threads and it increases with each created QQuickWidget. Together with the VmSize. I think those threads are no GUI threads, but perhaps for some interactions between Qt Quick and Qt Widget. Perhaps for the Qml Context or Engine?
Here is some code to reproduce this behavior. Works for me on our embedded target and in Ubuntu.
void MainWindow::on_pushButton_clicked() { QQuickWidget* quickWidget = new QQuickWidget(this); quickWidget->setSource(QUrl("qrc:/RedRectangle.qml")); quickWidget->show(); QProcess process; process.start("cat", QStringList() << QString("/proc/%1/status").arg(QCoreApplication::applicationPid())); process.waitForFinished(); QString output = process.readAll(); qDebug() << "Number of threads:" << output.split("Threads").at(1).split("\n").at(0).mid(2); qDebug() << "VmSize:" << output.split("VmSize").at(1).split("\n").at(0).mid(4); process.close(); }And here the output of this code:
Number of threads: "7" VmSize: "175096 kB" Number of threads: "8" VmSize: "197020 kB" Number of threads: "9" VmSize: "217928 kB" Number of threads: "10" VmSize: "238832 kB"Edit:
I added the VmSize. Each QQuickWidgets reserves about 20 MB of RAM. 8 MB of those are for the stack.Edit:
I looked into the documentation of QQuickWidget and saw that there is a constructor which needs a QQmlEngine. When creating a global engine-object and using this for the QQuickWidgets there are no additional threads and just a bit additional memory usage. I will try to create a global engine and use local contexts for each QQuickWidget in our application. If the application will work as before, this could reduce the memory usage drastically.Edit:
I finally found a solution. The problem was to find a way to pass an own QQmlContext to a QQuickWidget, but use the same QQmlEngine at the same time. I had to take the indirection over the QQmlComponent. Here is some code:QQmlEngine* engine = new QQmlEngine(); QQmlContext* context = new QQmlContext(engine); engine->rootContext()->setContextProperty("message", "marco"); context->setContextProperty("message", "polo"); QQuickWidget* quickWidget = new QQuickWidget(engine, this); quickWidget->setResizeMode(QQuickWidget::SizeRootObjectToView); QQmlComponent* component = new QQmlComponent(engine, "qrc:/MarcoPolo.qml"); quickWidget->setContent(component->url(), component, component->create(context)); ui->verticalLayout->addWidget(quickWidget);This reduced the virtual memory usage and the number of threads drastically.
Please tell me, if anyone has a simpler solution.