[Development] QML pixmap caching

David Faure david.faure at kdab.com
Tue Jul 24 12:30:25 CEST 2012


On Monday 23 July 2012 23:58:16 martin.jones at nokia.com wrote:
> > So maybe this should be configurable?
> 
> Perhaps.  I'm wary of exposing details of the current implementation in API.

I'm not sure how this is an implementation detail. It can be as high level as "cache size in MB".
QPixmapCache has that. ListView has "bufferSize" for something similar (but PathView is
missing it, which is what's creating this problem in the first place). Overall, I think giving tools
to tune the RAM vs CPU tradeoff is important, especially with a focus on animations
and embedded... (therefore both CPU and RAM can be important limitations, depending
on the actual use cases).

> > Or is the only option to create my own QDeclarativeImageProvider which
> > keeps everything in memory?
> 
> This is the only option at the moment.

So, I've done that, and discovered another small issue: since I do my own caching in the
provider, I want to bypass the internal caching, which I do with "cache: false" in the
image elements. However when the images are unref'ed, they still count as part of the m_unreferencedCost,
which triggers "cache shrinking".
Shouldn't this be skipped for non-cached images?

@@ -646,12 +646,15 @@ void QDeclarativePixmapStore::unreferencePixmap(QDeclarativePixmapData *data)
     if (!m_lastUnreferencedPixmap)
         m_lastUnreferencedPixmap = data;
 
-    m_unreferencedCost += data->cost();
+    if (data->inCache) {
+        m_unreferencedCost += data->cost();
 
-    shrinkCache(-1); // Shrink the cache incase it has become larger than cache_limit
+        shrinkCache(-1); // Shrink the cache incase it has become larger than cache_limit
 
-    if (m_timerId == -1 && m_unreferencedPixmaps) 
-        m_timerId = startTimer(CACHE_EXPIRE_TIME * 1000);
+        if (m_timerId == -1 && m_unreferencedPixmaps) {
+            m_timerId = startTimer(CACHE_EXPIRE_TIME * 1000);
+        }
+    }
 }
 
 void QDeclarativePixmapStore::referencePixmap(QDeclarativePixmapData *data)
@@ -670,14 +673,18 @@ void QDeclarativePixmapStore::referencePixmap(QDeclarativePixmapData *data)
     data->prevUnreferencedPtr = 0;
     data->prevUnreferenced = 0;
 
-    m_unreferencedCost -= data->cost();
+    if (data->inCache) {
+        m_unreferencedCost -= data->cost();
+    }
 }
 
This works great here, but I'm wondering if un-cached pixmaps should go into m_lastUnreferencedPixmap
and m_unreferencedPixmaps. Maybe the above patch makes that list grow forever, if all images
are uncached?

> > I'll do that for now, but it seems like there should be an easier way to
> > tell QML "keep stuff in cache as long as the cache isn't too big" (and
> > the cache size could possibly be made configurable, too, like in
> > QPixmapCache).
> I agree that the current strategy is too aggressively discarding
> images.  The simplest solution I can think of is to have a lower and upper
> bound, so that the cache allows up to say 25% of its capacity to remain
> indefinitely.  

That would work ok in some cases and it would already be an improvement IMHO,
but of course one might want to tune this number too...

> It should be possible to set the cache size too.  This is a
> task that has been around for some time
> https://bugreports.qt-project.org/browse/QTBUG-19507

Could you advise the guy in that report, about which API would be good for this?
Then he can finish the patch and contribute it...

-- 
David Faure | david.faure at kdab.com | Managing Director KDAB France
KDAB (France) S.A.S., a KDAB Group company
Tel. France +33 (0)4 90 84 08 53, Sweden (HQ) +46-563-540090
KDAB - Qt Experts - Platform-independent software solutions




More information about the Development mailing list