为啥 QML Image 占用这么多内存?减慢申请

Posted

技术标签:

【中文标题】为啥 QML Image 占用这么多内存?减慢申请【英文标题】:Why is QML Image taking up so much memory? Slowing down application为什么 QML Image 占用这么多内存?减慢申请 【发布时间】:2019-08-07 19:22:46 【问题描述】:

当我加载图像时,我的 Qt Quick 应用程序速度变慢并且消耗了太多内存。我正在加载大约 5 个很大的 PNG 图片,每个大约 50MB。

在这里查看尺寸:

在加载图像之前,应用程序的内存消耗约为 300MB,还不错......然后当我加载 5 个图像时,它会跳到 4.4 GB 并停留在那里! (我尝试在完成时调用 gc(),它什么也没做)

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

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'

“活动监视器”的另一个屏幕截图

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

有关如何解决此问题的任何 cmets 或建议?谢谢!我正在使用 Qt 5.12

【问题讨论】:

图片的像素大小是多少? 就我而言,我从未见过在 Windows 和 Linux 上如此糟糕的消耗。通常它可能需要 200% 的图像大小、好的缓存等。不幸的是我无法在 Mac 中测试它。无论如何,如果你只想显示图像,我的意思是没有效果等,你可以编写你的自定义项目,它只是在画布上绘制图像而不是其他任何东西。 @BenjaminT 像素大小为 11,000 x 11,000 【参考方案1】:

PNG 文件大小与运行时的 RAM 使用无关。 以 PNG 格式存储的图像经过压缩,因此尺寸可能非常小。

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

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

memory = 1 byte * 4 channels * width * height
对于 1920x1080 的图像,它将提供 8,100 KiB。 对于 4K 图像:32,400 KiB 对于 11,000x11,000 图像:462 MiB

因此,加载多个 11,000x11,000 图像的程序消耗几 GB 的 RAM 也就不足为奇了。

对于单个图像而言,报告的 1.39 GB 消耗仍然有点令人惊讶。但有几种可能的解释:

Qt(和 OpenGL)需要制作和存储图像的副本。 您的 PNG 每个通道使用超过 8 位。我认为PNG每个通道最多可以达到16位。如果是您的情况,则 RAM 消耗会增加一倍。 图像存储对大图像有内存开销,导致内存消耗增加。 某处有错误...

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

【讨论】:

【参考方案2】:

你可以试试这个 QML 图像属性来尝试调整图像大小

 sourceSize.height:height
 sourceSize.width: width

https://doc.qt.io/qt-5/qml-qtquick-image.html#sourceSize-prop

【讨论】:

另外,您可以在加载之前使用 QQuickImageProvider 在 C++ 中调整图像大小

以上是关于为啥 QML Image 占用这么多内存?减慢申请的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的 UIImage 占用这么多内存?

为啥 iOS 设备上的 glGenerateMipmap() 会占用这么多客户端内存?

为啥训练我的朴素贝叶斯分类器会占用这么多内存?

Pytorch:为啥`tensor`变量占用的内存这么小?

HTML:为啥元素占用这么多宽度?

为啥 dequeue() 占用这么多处理器时间?