]> cloud.milkyroute.net Git - dolphin.git/commitdiff
Improve performance for creating previews
authorPeter Penz <peter.penz19@gmail.com>
Tue, 2 Aug 2011 17:47:06 +0000 (19:47 +0200)
committerPeter Penz <peter.penz19@gmail.com>
Tue, 2 Aug 2011 17:54:39 +0000 (19:54 +0200)
The overall time for creating previews is faster the more items
are passed to KIO::previewJob() in parallel instead of passing
e.g. only 100 items once and start several KIO::previewJobs
sequentially.

However in the worst case KIO::previewJob() might
block the application for several seconds if the
MIME-type of the passed KFileItems are unknown and e.g. 10000 items
are forwarded.

So KFileItemModelRolesUpdater will now take care to resolve as many
MIME-types as possible until a timeout is reached and will only pass
those items to KIO::previewJob().

For huge image folders, where the MIME-type can be determined very
fast, this means that the overall time for creating previews will
decrease without blocking the application. For "worst case" directories
where resolving the MIME-type can get very expensive this approach
assures no blocking of the user-interface although the overall time
until all previews are generated might slightly increase.

src/kitemviews/kfileitemmodelrolesupdater.cpp
src/kitemviews/kfileitemmodelrolesupdater.h

index 4d36a4e056c500b3ba799f1c4f965f143fe36bf0..5b589a9d5e743fc11fec10b7506a5e1ded26de0a 100644 (file)
 #define KFILEITEMMODELROLESUPDATER_DEBUG
 
 namespace {
 #define KFILEITEMMODELROLESUPDATER_DEBUG
 
 namespace {
+    // Maximum time in ms that the KFileItemModelRolesUpdater
+    // may perform a blocking operation
+    const int MaxBlockTimeout = 200;
+
+    // Maximum number of items that will get resolved synchronously.
+    // The value should roughly represent the number of maximum visible
+    // items, as it does not make sense to resolve more items synchronously
+    // and probably reach the MaxBlockTimeout because of invisible items.
     const int MaxResolveItemsCount = 100;
 }
 
     const int MaxResolveItemsCount = 100;
 }
 
@@ -344,9 +352,8 @@ void KFileItemModelRolesUpdater::slotPreviewJobFinished(KJob* job)
         return;
     }
 
         return;
     }
 
-    const KFileItemList visibleItems   = sortedItems(m_pendingVisibleItems);
-    const KFileItemList invisibleItems = itemSubSet(m_pendingInvisibleItems, MaxResolveItemsCount - visibleItems.count());
-    startPreviewJob(visibleItems + invisibleItems);
+    const KFileItemList visibleItems = sortedItems(m_pendingVisibleItems);
+    startPreviewJob(visibleItems + m_pendingInvisibleItems.toList());
 }
 
 void KFileItemModelRolesUpdater::resolvePendingRoles()
 }
 
 void KFileItemModelRolesUpdater::resolvePendingRoles()
@@ -358,10 +365,9 @@ void KFileItemModelRolesUpdater::resolvePendingRoles()
                               || m_roles.contains("type");
     const ResolveHint resolveHint = hasSlowRoles ? ResolveFast : ResolveAll;
 
                               || m_roles.contains("type");
     const ResolveHint resolveHint = hasSlowRoles ? ResolveFast : ResolveAll;
 
-    // Resolving the MIME type can be expensive. Assure that not more than 200 ms are
+    // Resolving the MIME type can be expensive. Assure that not more than MaxBlockTimeout ms are
     // spend for resolving them synchronously. Usually this is more than enough to determine
     // all visible items, but there are corner cases where this limit gets easily exceeded.
     // spend for resolving them synchronously. Usually this is more than enough to determine
     // all visible items, but there are corner cases where this limit gets easily exceeded.
-    const int MaxTime = 200;
     QElapsedTimer timer;
     timer.start();
 
     QElapsedTimer timer;
     timer.start();
 
@@ -377,7 +383,7 @@ void KFileItemModelRolesUpdater::resolvePendingRoles()
         }
         ++resolvedCount;
 
         }
         ++resolvedCount;
 
-        if (timer.elapsed() > MaxTime) {
+        if (timer.elapsed() > MaxBlockTimeout) {
             break;
         }
     }
             break;
         }
     }
@@ -397,7 +403,7 @@ void KFileItemModelRolesUpdater::resolvePendingRoles()
     }
 
     int index = 0;
     }
 
     int index = 0;
-    while (resolvedCount < MaxResolveItemsCount && index < invisibleItems.count() && timer.elapsed() <= MaxTime) {
+    while (resolvedCount < MaxResolveItemsCount && index < invisibleItems.count() && timer.elapsed() <= MaxBlockTimeout) {
         const KFileItem item = invisibleItems.at(index);
         applyResolvedRoles(item, resolveHint);
 
         const KFileItem item = invisibleItems.at(index);
         applyResolvedRoles(item, resolveHint);
 
@@ -418,8 +424,9 @@ void KFileItemModelRolesUpdater::resolvePendingRoles()
     }
 
 #ifdef KFILEITEMMODELROLESUPDATER_DEBUG
     }
 
 #ifdef KFILEITEMMODELROLESUPDATER_DEBUG
-    if (timer.elapsed() > MaxTime) {
-        kDebug() << "Maximum time exceeded, skipping items... Remaining visible:" << m_pendingVisibleItems.count()
+    if (timer.elapsed() > MaxBlockTimeout) {
+        kDebug() << "Maximum time of" << MaxBlockTimeout
+                 << "ms exceeded, skipping items... Remaining visible:" << m_pendingVisibleItems.count()
                  << "invisible:" << m_pendingInvisibleItems.count();
     }
     kDebug() << "[TIME] Resolved pending roles:" << timer.elapsed();
                  << "invisible:" << m_pendingInvisibleItems.count();
     }
     kDebug() << "[TIME] Resolved pending roles:" << timer.elapsed();
@@ -482,16 +489,28 @@ void KFileItemModelRolesUpdater::startPreviewJob(const KFileItemList& items)
     const QSize cacheSize = (m_iconSize.width() > 128) || (m_iconSize.height() > 128)
                             ? QSize(256, 256) : QSize(128, 128);
 
     const QSize cacheSize = (m_iconSize.width() > 128) || (m_iconSize.height() > 128)
                             ? QSize(256, 256) : QSize(128, 128);
 
-    KJob* job;
-    if (items.count() <= MaxResolveItemsCount) {
-        job = KIO::filePreview(items, cacheSize, &m_enabledPlugins);
-    } else {
-        KFileItemList itemsSubSet;
-        for (int i = 0; i <= MaxResolveItemsCount; ++i) {
-            itemsSubSet.append(items.at(i));
+    // KIO::filePreview() will request the MIME-type of all passed items, which (in the
+    // worst case) might block the application for several seconds. To prevent such
+    // a blocking the MIME-type of the items will determined until the MaxBlockTimeout
+    // has been reached and only those items will get passed. As soon as the MIME-type
+    // has been resolved once KIO::filePreview() can already access the resolved
+    // MIME-type in a fast way.
+    QElapsedTimer timer;
+    timer.start();
+    KFileItemList itemSubSet;
+    for (int i = 0; i < items.count(); ++i) {
+        KFileItem item = items.at(i);
+        item.determineMimeType();
+        itemSubSet.append(items.at(i));
+        if (timer.elapsed() > MaxBlockTimeout) {
+#ifdef KFILEITEMMODELROLESUPDATER_DEBUG
+            kDebug() << "Maximum time of" << MaxBlockTimeout << "ms exceeded, creating only previews for"
+                     << (i + 1) << "items," << (items.count() - (i + 1)) << "will be resolved later";
+#endif
+            break;
         }
         }
-        job = KIO::filePreview(itemsSubSet, cacheSize, &m_enabledPlugins);
     }
     }
+    KJob* job = KIO::filePreview(itemSubSet, cacheSize, &m_enabledPlugins);
 
     connect(job,  SIGNAL(gotPreview(KFileItem,QPixmap)),
             this, SLOT(slotGotPreview(KFileItem,QPixmap)));
 
     connect(job,  SIGNAL(gotPreview(KFileItem,QPixmap)),
             this, SLOT(slotGotPreview(KFileItem,QPixmap)));
@@ -711,24 +730,6 @@ KFileItemList KFileItemModelRolesUpdater::sortedItems(const QSet<KFileItem>& ite
     return itemList;
 }
 
     return itemList;
 }
 
-KFileItemList KFileItemModelRolesUpdater::itemSubSet(const QSet<KFileItem>& items, int count)
-{
-    KFileItemList itemList;
-
-    int index = 0;
-    QSetIterator<KFileItem> it(items);
-    while (it.hasNext() && index < count) {
-        const KFileItem item = it.next();
-        if (item.isNull()) {
-            continue;
-        }
-        itemList.append(item);
-        ++index;
-    }
-
-    return itemList;
-}
-
 int KFileItemModelRolesUpdater::subDirectoriesCount(const QString& path)
 {
 #ifdef Q_WS_WIN
 int KFileItemModelRolesUpdater::subDirectoriesCount(const QString& path)
 {
 #ifdef Q_WS_WIN
index 4931f9d6446367c266899bdb6f5a6f27ece28eed..3b173567e14105a41ba9593a44b1598b8908c6b5 100644 (file)
@@ -137,7 +137,6 @@ private:
 
     KFileItemList sortedItems(const QSet<KFileItem>& items) const;
 
 
     KFileItemList sortedItems(const QSet<KFileItem>& items) const;
 
-    static KFileItemList itemSubSet(const QSet<KFileItem>& items, int count);
     static int subDirectoriesCount(const QString& path);
 
 private:
     static int subDirectoriesCount(const QString& path);
 
 private: