Details
-
Bug
-
Resolution: Fixed
-
P2: Important
-
5.15.2
-
WASM environment inside latest Chrome
versions are in the description
Description
High CPU usage when using threads (only in WASM)
QT version: 5.15.2
EMSDK version: 2.0.6
Minisample: provided
Browser: Chrome 91.0.4472.77
Description
Upon creating a multi-threaded application, when the „background" thread is started, its event loop is keeping a CPU core 100% loaded. It has at least 2 drawbacks: the overall application performance decreases and due to the increased load, the mobile device requires extra cooling (fan spin up) and decreased battery time.
Impact
Customers report decreased interactivity and annoyance of fan spinning, defining application as a wrongly designed one.
Cross-check
Same application compiled for Windows (VS 2015, Qt native) does not use more than 0.01% CPU.
Reproduction
The very minimal sample is attached. After successful compilation, the result is a WASM application running in a browser. It should contain a button with text „TEST" and a QtextBroswer as a log window.
Upon pressing the button the on_text_clicked() is executed (basepanel.h). By default, cnt=0, so a new thread is constructed (signalThread = new ThreadSlot()). This thread would occupy one CPU core.
The class threadSlot is stripped down to its possible minimum. The relevant function here is the run() in which only the Qthread::exec() is called.
Right after the first press, the CPU load goes to one core level (the test PC has 8 cores, meaning that 1 core full load is 12.5%), and that load could be increased by creating subseqent threads (not part of the minimal sample)
In the process explorer it could be seen that the one core load (around 13%) is made up from the load of 2 threads: one foreground and one background thread.
Digging deeper into the issue, the following callstacks are found.These callstacks are steadily reproducible upon subsequent runs.
FOREGROUND THREAD CALLSTACK
worker.onmessage (VM904:1363)
postMessage (async)
__emscripten_notify_thread_queue (158f6eda-8619-4e35-9684-77fd4e0f9ce7:5609)
do_emscripten_dispatch_to_thread (block_test.wasm:0x7edeb9)
emscripten_run_in_main_runtime_thread_js (block_test.wasm:0x7ee407)
_emscripten_proxy_to_main_thread_js (158f6eda-8619-4e35-9684-77fd4e0f9ce7:10433)
___sys_poll (158f6eda-8619-4e35-9684-77fd4e0f9ce7:4643)
poll (block_test.wasm:0x7ca79d)
qt_safe_poll(pollfd*, unsigned long, timespec const*) (block_test.wasm:0x766212)
QEventDispatcherUNIX::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) (block_test.wasm:0x767838)
QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) (block_test.wasm:0x73499c)
QThread::exec() (block_test.wasm:0x6258b3)
ThreadSlot::run() (block_test.wasm:0xf69b)
QThreadPrivate::start(void*) (block_test.wasm:0x625d7e)
dynCall (158f6eda-8619-4e35-9684-77fd4e0f9ce7:1047)
onmessage (block_test.worker.js:108)
Worker.postMessage (async)
worker.runPthread (VM904:11345)
spawnThread (VM904:11348)
_pthread_create (VM904:11449)
QThread::start(QThread::Priority) (block_test.wasm:0x62625f)
ThreadSlot::ThreadSlot() (block_test.wasm:0xf3d4)
BasePanel::on_test_clicked() (block_test.wasm:0xf317)
BasePanel::qt_metacall(QMetaObject::Call, int, void**) (block_test.wasm:0xf650)
QMetaObject::metacall(QObject*, QMetaObject::Call, int, void**) (block_test.wasm:0x73d65f)
void doActivate<false>(QObject*, int, void**) (block_test.wasm:0x74d6fc)
QMetaObject::activate(QObject*, QMetaObject const*, int, void**) (block_test.wasm:0x752e2f)
QAbstractButtonPrivate::emitClicked() (block_test.wasm:0x1fedf0)
QAbstractButtonPrivate::click() (block_test.wasm:0x1ff07c)
QAbstractButton::mouseReleaseEvent(QMouseEvent*) (block_test.wasm:0x1ffc99)
QWidget::event(QEvent*) (block_test.wasm:0x170dd8)
QAbstractButton::event(QEvent*) (block_test.wasm:0x1ff86b)
QPushButton::event(QEvent*) (block_test.wasm:0x25f4fb)
QApplicationPrivate::notify_helper(QObject*, QEvent*) (block_test.wasm:0x13cd2b)
QApplication::notify(QObject*, QEvent*) (block_test.wasm:0x13e95c)
QCoreApplication::notifyInternal2(QObject*, QEvent*) (block_test.wasm:0x739470)
QCoreApplication::sendSpontaneousEvent(QObject*, QEvent*) (block_test.wasm:0x739f85)
QApplicationPrivate::sendMouseEvent(QWidget*, QMouseEvent*, QWidget*, QWidget*, QWidget**, QPointer<QWidget>&, bool, bool) (block_test.wasm:0x13d529)
QWidgetWindow::handleMouseEvent(QMouseEvent*) (block_test.wasm:0x18cd93)
QWidgetWindow::event(QEvent*) (block_test.wasm:0x18aab9)
QApplicationPrivate::notify_helper(QObject*, QEvent*) (block_test.wasm:0x13cd2b)
QApplication::notify(QObject*, QEvent*) (block_test.wasm:0x140a2b)
QCoreApplication::notifyInternal2(QObject*, QEvent*) (block_test.wasm:0x739470)
QCoreApplication::sendSpontaneousEvent(QObject*, QEvent*) (block_test.wasm:0x739f85)
QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::MouseEvent*) (block_test.wasm:0x3af407)
QGuiApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent*) (block_test.wasm:0x3adc19)
bool QWindowSystemInterfacePrivate::handleWindowSystemEvent<QWindowSystemInterface::SynchronousDelivery>(QWindowSystemInterfacePrivate::WindowSystemEvent*) (block_test.wasm:0x39b3c1)
bool QWindowSystemInterface::handleMouseEvent<QWindowSystemInterface::SynchronousDelivery>(QWindow*, unsigned long, QPointF const&, QPointF const&, QFlags<Qt::MouseButton>, Qt::MouseButton, QEvent::Type, QFlags<Qt::KeyboardModifier>, Qt::MouseEventSource) (block_test.wasm:0x39ee73)
QWasmEventTranslator::processMouse(int, EmscriptenMouseEvent const*) (block_test.wasm:0x14c5e)
QWasmEventTranslator::mouse_cb(int, EmscriptenMouseEvent const*, void*) (block_test.wasm:0x13e24)
mouseEventHandlerFunc (VM904:10684)
jsEventHandler (VM904:6798)
BACKGROUND THREAD CALLSTACK
_emscripten_futex_wait (158f6eda-8619-4e35-9684-77fd4e0f9ce7:6687)
emscripten_wait_for_call_v (block_test.wasm:0x7edd00)
emscripten_run_in_main_runtime_thread_js (block_test.wasm:0x7ee40e)
_emscripten_proxy_to_main_thread_js (158f6eda-8619-4e35-9684-77fd4e0f9ce7:10433)
___sys_poll (158f6eda-8619-4e35-9684-77fd4e0f9ce7:4643)
poll (block_test.wasm:0x7ca79d)
qt_safe_poll(pollfd*, unsigned long, timespec const*) (block_test.wasm:0x766212)
QEventDispatcherUNIX::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) (block_test.wasm:0x767838)
QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) (block_test.wasm:0x73499c)
QThread::exec() (block_test.wasm:0x6258b3)
ThreadSlot::run() (block_test.wasm:0xf69b)
QThreadPrivate::start(void*) (block_test.wasm:0x625d7e)
dynCall (158f6eda-8619-4e35-9684-77fd4e0f9ce7:1047)
onmessage (block_test.worker.js:108)
Worker.postMessage (async)
worker.runPthread (VM904:11345)
spawnThread (VM904:11348)
_pthread_create (VM904:11449)
QThread::start(QThread::Priority) (block_test.wasm:0x62625f)
ThreadSlot::ThreadSlot() (block_test.wasm:0xf3d4)
BasePanel::on_test_clicked() (block_test.wasm:0xf317)
BasePanel::qt_metacall(QMetaObject::Call, int, void**) (block_test.wasm:0xf650)
QMetaObject::metacall(QObject*, QMetaObject::Call, int, void**) (block_test.wasm:0x73d65f)
void doActivate<false>(QObject*, int, void**) (block_test.wasm:0x74d6fc)
QMetaObject::activate(QObject*, QMetaObject const*, int, void**) (block_test.wasm:0x752e2f)
QAbstractButtonPrivate::emitClicked() (block_test.wasm:0x1fedf0)
QAbstractButtonPrivate::click() (block_test.wasm:0x1ff07c)
QAbstractButton::mouseReleaseEvent(QMouseEvent*) (block_test.wasm:0x1ffc99)
QWidget::event(QEvent*) (block_test.wasm:0x170dd8)
QAbstractButton::event(QEvent*) (block_test.wasm:0x1ff86b)
QPushButton::event(QEvent*) (block_test.wasm:0x25f4fb)
QApplicationPrivate::notify_helper(QObject*, QEvent*) (block_test.wasm:0x13cd2b)
QApplication::notify(QObject*, QEvent*) (block_test.wasm:0x13e95c)
QCoreApplication::notifyInternal2(QObject*, QEvent*) (block_test.wasm:0x739470)
QCoreApplication::sendSpontaneousEvent(QObject*, QEvent*) (block_test.wasm:0x739f85)
QApplicationPrivate::sendMouseEvent(QWidget*, QMouseEvent*, QWidget*, QWidget*, QWidget**, QPointer<QWidget>&, bool, bool) (block_test.wasm:0x13d529)
QWidgetWindow::handleMouseEvent(QMouseEvent*) (block_test.wasm:0x18cd93)
QWidgetWindow::event(QEvent*) (block_test.wasm:0x18aab9)
QApplicationPrivate::notify_helper(QObject*, QEvent*) (block_test.wasm:0x13cd2b)
QApplication::notify(QObject*, QEvent*) (block_test.wasm:0x140a2b)
QCoreApplication::notifyInternal2(QObject*, QEvent*) (block_test.wasm:0x739470)
QCoreApplication::sendSpontaneousEvent(QObject*, QEvent*) (block_test.wasm:0x739f85)
QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::MouseEvent*) (block_test.wasm:0x3af407)
QGuiApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent*) (block_test.wasm:0x3adc19)
bool QWindowSystemInterfacePrivate::handleWindowSystemEvent<QWindowSystemInterface::SynchronousDelivery>(QWindowSystemInterfacePrivate::WindowSystemEvent*) (block_test.wasm:0x39b3c1)
bool QWindowSystemInterface::handleMouseEvent<QWindowSystemInterface::SynchronousDelivery>(QWindow*, unsigned long, QPointF const&, QPointF const&, QFlags<Qt::MouseButton>, Qt::MouseButton, QEvent::Type, QFlags<Qt::KeyboardModifier>, Qt::MouseEventSource) (block_test.wasm:0x39ee73)
QWasmEventTranslator::processMouse(int, EmscriptenMouseEvent const*) (block_test.wasm:0x14c5e)
QWasmEventTranslator::mouse_cb(int, EmscriptenMouseEvent const*, void*) (block_test.wasm:0x13e24)
mouseEventHandlerFunc (VM904:10684)
jsEventHandler (VM904:6798)