Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-94344

High CPU load in WASM threaded application

    XMLWordPrintable

Details

    • WebAssembly

    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)

       

       

       

       

      Attachments

        1. wasm-6.3-threads-test.main.cpp
          1 kB
        2. thread-tester copy.zip
          3 kB
        3. thread-destroyer-example.zip
          4 kB
        4. thread-destroyer-1.zip
          4 kB
        5. thread-destroyer.zip
          4 kB
        6. Screenshot 2021-09-22 at 16.06.08.png
          Screenshot 2021-09-22 at 16.06.08.png
          73 kB
        7. qt_cpu_overload.pdf
          204 kB
        8. BLOCK.tar.gz
          2 kB
        For Gerrit Dashboard: QTBUG-94344
        # Subject Branch Project Status CR V

        Activity

          People

            sorvig Morten Sørvig
            hyperborg Imre Nagy
            Votes:
            5 Vote for this issue
            Watchers:
            8 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews