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

Memory that is mmap'ed for dynamic QML objects do not get munmap'ed after object destruction

    XMLWordPrintable

Details

    • Linux/X11

    Description

      For QML objects that are dynamically created (e.g. via Component.createObject(), Loader, or Repeater), even if they are properly destroyed, the memory does not get unmapped and is therefore unavailable to other processes. This can cause problems on resource-constrained systems that host complex GUIs.

       

      Test code

      import QtQuick 2.15
      import QtQuick.Controls 2.15
      
      ApplicationWindow {
          id: window
          visible: true
          width: 640
          height: 480
      
          property var vector: []
      
          Column {
              Button {
                  text: "Create Objects"
                  onClicked: {
                      const N = 50000
                      console.log("Creating", N, "objects...")
                      for (let i = 0; i < N; ++i) {
                          let obj = objComp.createObject(window)
                          vector.push(obj)
                      }
                  }
              }
              Button {
                  text: "Destroy Objects"
                  onClicked: {
                      console.log("Destroying", vector.length, "objects...")
                      for (let i = 0; i < vector.length; ++i)
                          vector[i].destroy()
                      vector = []
                  }
              }
              Button {
                  text: "Collect Garbage"
                  onClicked: {
                      console.log("Running garbage collector...")
                      gc()
                  }
              }
          }
      
          Component{
              id: objComp
              QtObject {
                  //Component.onCompleted: console.log("QtObject created")
                  //Component.onDestruction: console.log("QtObject destroyed")
              }
          }
      }
      

       

      Steps to reproduce

      Take note of the RAM usage at the end of each step below ("Memory" column of Task Manager on Windows; the "RSS" field of `pmap -x` or the "RES" field of `top` on Linux)

      1. Build and run the above code
      2. Click "Create Objects" 10 times (to create 500k objects)
      3. Click "Destroy Objects"
      4. Click "Collect Garbage"

       

      Results

      The following were observed in Debug mode, using Qt 5.15.10 

        Windows 10 Pro 21H2 (MSVC 2019 x64) Ubuntu 20.04 (GCC 9.4.0)
      1. At startup 40 MB 100 MB
      2. After 10 clicks (500k objects) 480 MB 420 MB
      3. After destroying objects 200 MB 460 MB
      4. After collecting garbage 70 MB 400 MB

      Windows' RAM usage returned almost (but not quite) to startup levels, while Linux didn't get anywhere near that.

       

      Other notes

      • For both platforms, Qt 6.2.5 showed similar results, but suffered from much greater lag throughout the test.
      • If the vector is filled with 20 million numbers instead of QML objects, Step #3 reaches >600MB while Step #4 brings it back to 110 MB in Ubuntu 20.04

      Attachments

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            ulherman Ulf Hermann
            skoh-qt Sze Howe Koh
            Votes:
            0 Vote for this issue
            Watchers:
            6 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There are no open Gerrit changes