Javascript 为什么QML映像占用这么多内存?减慢应用程序速度

Javascript 为什么QML映像占用这么多内存?减慢应用程序速度,javascript,qt,qml,qtquick2,qtquickcontrols2,Javascript,Qt,Qml,Qtquick2,Qtquickcontrols2,我的Qt Quick应用程序在加载图像时速度变慢,占用的内存太多。我正在加载大约5个大的PNG图像,每个大约50MB 请参见此处的尺寸: 在加载图像之前,应用程序的内存消耗大约为300MB,还不错……然后当我加载5个图像时,它会跳到4.4GB并保持不变!(我尝试在完成时调用gc(),但没有任何效果) 所以我做了一些实验。我编写了这个基本应用程序,只是一个QML映像。我在没有图像源的情况下执行,内存为28.7MB import QtQuick 2.12 import QtQuick.Contro

我的Qt Quick应用程序在加载图像时速度变慢,占用的内存太多。我正在加载大约5个大的PNG图像,每个大约50MB

请参见此处的尺寸:

在加载图像之前,应用程序的内存消耗大约为300MB,还不错……然后当我加载5个图像时,它会跳到4.4GB并保持不变!(我尝试在完成时调用gc(),但没有任何效果)

所以我做了一些实验。我编写了这个基本应用程序,只是一个QML映像。我在没有图像源的情况下执行,内存为28.7MB

import QtQuick 2.12
import QtQuick.Controls 2.3

Image {
    id: imageId
    anchors.fill: parent
    fillMode: Image.PreserveAspectFit
    anchors.centerIn: parent
    //source: 'test_images/1.png'
}
这是Mac“活动监视器”的屏幕截图

当我添加50MB图像作为源时,内存消耗跃升到1.39GB并保持不变!即使在gc()之后,它什么也没做

import QtQuick 2.12
import QtQuick.Controls 2.3

Image {
    id: imageId
    anchors.fill: parent
    fillMode: Image.PreserveAspectFit
    anchors.centerIn: parent
    source: 'test_images/1.png'
}
“活动监视器”的另一个屏幕截图

这个图像对象发生了什么事情,使它消耗了1.39GB的内存!图像只有50MB!这是我应用程序问题的根源,它使我的应用程序几乎无法使用。这是QtQuick平台的一个主要问题


对如何解决这一问题有何意见或建议?谢谢我使用的是Qt5.12

PNG文件大小与运行时的RAM使用情况无关。 存储为PNG的图像是压缩的,因此大小可能非常小

在程序中加载和显示PNG图像时,图像将被解压缩,并使用更多内存

通常,对于具有4个通道(RGBA)且每个通道8位的图像,内存占用将为:

memory = 1 byte * 4 channels * width * height
  • 对于1920x1080图像,它将提供8100千磅
  • 对于4K图像:32400千磅
  • 对于11000x11000映像:462 MiB
因此,一个加载多个11000x11000图像的程序消耗几GB的RAM并不令人惊讶

不过,对于单个图像而言,1.39 GB的消耗量还是有点令人惊讶。但有几种可能的解释:

  • Qt(和OpenGL)需要制作和存储图像的副本
  • 您的PNG每个通道使用超过8位。我认为PNG每通道可以达到16位。如果是您的情况,它将使RAM消耗加倍
  • 对于大图像,图像存储有内存开销,这会增加内存消耗
  • 某处有一只虫子

有可能的解决方案可以减少内存占用,但我认为它们都需要减少图像大小。考虑到大多数屏幕为4K或更小,您永远不需要在给定时间显示所有图像像素。因此,你可以做的是裁剪或调整图像的大小,以满足你的需要。这可以静态完成(即编译前自己完成),也可以在运行时动态完成:加载图像、计算缩小后的图像并卸载原始图像。

PNG文件大小与运行时的RAM使用情况无关。 存储为PNG的图像是压缩的,因此大小可能非常小

在程序中加载和显示PNG图像时,图像将被解压缩,并使用更多内存

通常,对于具有4个通道(RGBA)且每个通道8位的图像,内存占用将为:

memory = 1 byte * 4 channels * width * height
  • 对于1920x1080图像,它将提供8100千磅
  • 对于4K图像:32400千磅
  • 对于11000x11000映像:462 MiB
因此,一个加载多个11000x11000图像的程序消耗几GB的RAM并不令人惊讶

不过,对于单个图像而言,1.39 GB的消耗量还是有点令人惊讶。但有几种可能的解释:

  • Qt(和OpenGL)需要制作和存储图像的副本
  • 您的PNG每个通道使用超过8位。我认为PNG每通道可以达到16位。如果是您的情况,它将使RAM消耗加倍
  • 对于大图像,图像存储有内存开销,这会增加内存消耗
  • 某处有一只虫子

有可能的解决方案可以减少内存占用,但我认为它们都需要减少图像大小。考虑到大多数屏幕为4K或更小,您永远不需要在给定时间显示所有图像像素。因此,你可以做的是裁剪或调整图像的大小,以满足你的需要。这可以静态完成(即编译前自己完成),也可以在运行时动态完成:加载图像,计算缩小后的图像并卸载原始图像。

您可以尝试使用此QML图像属性来调整图像大小

 sourceSize.height:height
 sourceSize.width: width

您可以尝试使用此QML图像属性来调整图像大小

 sourceSize.height:height
 sourceSize.width: width

图像的像素大小是多少?就我而言,我从未见过在Windows和Linux上如此糟糕的消费。通常它需要大约200%的图像大小,ok缓存等。不幸的是,我不能在Mac上测试它。无论如何,如果你只想显示图像,我是说没有效果等,你可以编写你的自定义项目,只在画布上绘制图像,其他什么都不做。@BenjaminT图像的像素大小是11000 x 11000图像的像素大小是多少?至于我,我在Windows和Linux上从未见过如此可怕的消耗。通常它需要大约200%的图像大小,ok缓存等。不幸的是,我不能在Mac上测试它。无论如何,如果你想显示图像,我是说没有效果等等,你可以写你的自定义项目,只是在画布上绘制图像,没有其他。@ Bejayt的像素大小是11000×11000,也可以使用QQuiGeVeIVAdvor来调整C++中的图像大小,然后再加载。在加载之前,可以使用QQueGimeIvor提供C++中的图像大小调整