从源组件经常创建的缓存

时间:2015-12-17 16:57:29

标签: performance qt caching qml components

我处于高度动态的环境中,大量使用来自源的组件的动态实例化。当然,我担心每次动态创建对象时必须解析这些源的开销。当情况允许时,我使用手动缓存:

readonly property var componentCache: new Object
function create(type) {
    var comp = componentCache[type]
    if (comp === undefined) { // "cache miss"
        comp = Qt.createComponent(type)
        if (comp.status !== Component.Ready) {
            console.log("Component creation failed: " + comp.errorString())
            return null
        } else {
            componentCache[type] = comp
        }
    }
    return comp.createObject()
}

除了这并不总是适用之外,例如,使用Loader和一个需要使用setSource(source, properties)函数指定对象属性的组件。在这种情况下,无法使用手动缓存的Component,因为该函数只接受网址。文档模糊地提到"缓存"但是,对于来自该源的组件,该缓存是否是QML引擎范围还是更加可能 - 不仅仅是针对该特定Loader

  

如果此函数的活动属性为false   调用时,不会加载给定的源组件而是源   和初始属性将被缓存。当装载机处于活动状态时,   将使用initial创建源组件的实例   属性集。

问题是如何处理这个问题,甚至是必要的?也许Qt默认从源缓存中做组件?在避免冗余源加载(来自磁盘或更糟糕的网络),解析和组件准备方面,缓存肯定是有意义的,但是它的效果只会在过度动态实例化的情况下突出,而且#34;典型的" ; QML动态对象创建场景通常涉及一次性对象,在这种情况下,缓存将是无用的内存开销。在源可能在实例化之间发生变化的情况下,缓存也没有意义。

因为我没有时间去挖掘Qt API背后的私有实现,如果我不得不猜测,我说来源缓存的组件不太可能,但是仅仅是猜测,它可能也是错误的。

2 个答案:

答案 0 :(得分:1)

本身不是答案,我昨天闯入了组件缓存的问题 - 并且惊讶地发现Qt似乎缓存了组件。至少在创建动态组件时,与createComponent相关的日志语句仅在我的测试应用中出现一次。我已经四处搜索过,并且没有看到有关缓存的文档中的任何具体信息。我确实在QQMLEngine Class中遇到了几个有趣的方法。然后我遇到了release notes for Qt 5.4

  

Qt.createComponent()返回的组件不再是父级   到发动机。请务必持有参考或提供父母。

所以?如果提供了父级,则缓存(?)似乎是这种情况。 (并且对于5.5+?)如果您想自己管理它,请不要提供父母并保留参考。 (?)

QQmlEngine Class

  

QQmlEngine :: clearComponentCache()

清除引擎&#39>   内部组件缓存。

此函数导致该属性   先前由引擎加载的所有组件的元数据   销毁。所有先前加载的组件和属性绑定   对于从这些组件创建的所有现存对象将停止   function。

此函数将引擎返回到它的状态   不包含任何已加载的组件数据。这可能有用   为了重新加载前一个组件集的较小子集,或者   加载以前加载的组件的新版本。

一旦   组件缓存已被清除,组件必须先加载   可以创建新对象。

  

void QQmlEngine :: trimComponentCache()

     

修剪引擎的内部组件缓存。

     

此函数会导致任何已加载组件的属性元数据   这些目前尚未被销毁。

     

如果存在任何组件,则认为该组件正在使用中   组件本身的实例,其他组件的任何实例   使用组件或任何实例化的对象   组件。

答案 1 :(得分:0)

在玩了一些代码之后,看起来缓存也发生在"有问题的情况下" Loader.setSource()

this question运行示例代码,我发现由于Qt的硬编码限制,常规组件创建无法扩展超过10个节点的树:

// Do not create infinite recursion in object creation
static const int maxCreationDepth = 10;

如果常规方案中存在多个嵌套的10个组件实例,产品不正确的树并生成警告,则会导致组件实例化中止。

使用setSource()时不会发生这种情况,显而易见的原因是组件被缓存,因此不会发生组件实例化。