From c6494823c8b79a33bf333a1e3a2c58ac6d74dcea Mon Sep 17 00:00:00 2001 From: Frank Reininghaus Date: Wed, 5 Jun 2013 23:18:26 +0200 Subject: [PATCH] Reduce KFileItemModel memory usage by making use of implicit sharing The idea is based on http://milianw.de/blog/katekdevelop-sprint-vienna-2012-take-1 REVIEW: 110686 --- src/kitemviews/kfileitemmodel.cpp | 49 +++++++++++++++++++------------ src/kitemviews/kfileitemmodel.h | 6 ++++ 2 files changed, 37 insertions(+), 18 deletions(-) diff --git a/src/kitemviews/kfileitemmodel.cpp b/src/kitemviews/kfileitemmodel.cpp index d30d9e5be..5079b2fe2 100644 --- a/src/kitemviews/kfileitemmodel.cpp +++ b/src/kitemviews/kfileitemmodel.cpp @@ -167,7 +167,7 @@ bool KFileItemModel::setData(int index, const QHash& value QHashIterator it(values); while (it.hasNext()) { it.next(); - const QByteArray role = it.key(); + const QByteArray role = sharedValue(it.key()); const QVariant value = it.value(); if (currentValues[role] != value) { @@ -425,7 +425,7 @@ bool KFileItemModel::setExpanded(int index, bool expanded) } QHash values; - values.insert("isExpanded", expanded); + values.insert(sharedValue("isExpanded"), expanded); if (!setData(index, values)) { return false; } @@ -1252,27 +1252,27 @@ QHash KFileItemModel::retrieveData(const KFileItem& item, // KFileItem::iconName() can be very expensive if the MIME-type is unknown // and hence will be retrieved asynchronously by KFileItemModelRolesUpdater. QHash data; - data.insert("url", item.url()); + data.insert(sharedValue("url"), item.url()); const bool isDir = item.isDir(); if (m_requestRole[IsDirRole]) { - data.insert("isDir", isDir); + data.insert(sharedValue("isDir"), isDir); } if (m_requestRole[IsLinkRole]) { const bool isLink = item.isLink(); - data.insert("isLink", isLink); + data.insert(sharedValue("isLink"), isLink); } if (m_requestRole[NameRole]) { - data.insert("text", item.text()); + data.insert(sharedValue("text"), item.text()); } if (m_requestRole[SizeRole]) { if (isDir) { - data.insert("size", QVariant()); + data.insert(sharedValue("size"), QVariant()); } else { - data.insert("size", item.size()); + data.insert(sharedValue("size"), item.size()); } } @@ -1281,19 +1281,19 @@ QHash KFileItemModel::retrieveData(const KFileItem& item, // having several thousands of items. Instead the formatting of the // date-time will be done on-demand by the view when the date will be shown. const KDateTime dateTime = item.time(KFileItem::ModificationTime); - data.insert("date", dateTime.dateTime()); + data.insert(sharedValue("date"), dateTime.dateTime()); } if (m_requestRole[PermissionsRole]) { - data.insert("permissions", item.permissionsString()); + data.insert(sharedValue("permissions"), item.permissionsString()); } if (m_requestRole[OwnerRole]) { - data.insert("owner", item.user()); + data.insert(sharedValue("owner"), item.user()); } if (m_requestRole[GroupRole]) { - data.insert("group", item.group()); + data.insert(sharedValue("group"), item.group()); } if (m_requestRole[DestinationRole]) { @@ -1301,7 +1301,7 @@ QHash KFileItemModel::retrieveData(const KFileItem& item, if (destination.isEmpty()) { destination = QLatin1String("-"); } - data.insert("destination", destination); + data.insert(sharedValue("destination"), destination); } if (m_requestRole[PathRole]) { @@ -1324,11 +1324,11 @@ QHash KFileItemModel::retrieveData(const KFileItem& item, const int index = path.lastIndexOf(item.text()); path = path.mid(0, index - 1); - data.insert("path", path); + data.insert(sharedValue("path"), path); } if (m_requestRole[IsExpandableRole]) { - data.insert("isExpandable", item.isDir() && item.url() == item.targetUrl()); + data.insert(sharedValue("isExpandable"), item.isDir() && item.url() == item.targetUrl()); } if (m_requestRole[ExpandedParentsCountRole]) { @@ -1337,14 +1337,14 @@ QHash KFileItemModel::retrieveData(const KFileItem& item, level = parent->values["expandedParentsCount"].toInt() + 1; } - data.insert("expandedParentsCount", level); + data.insert(sharedValue("expandedParentsCount"), level); } if (item.isMimeTypeKnown()) { - data.insert("iconName", item.iconName()); + data.insert(sharedValue("iconName"), item.iconName()); if (m_requestRole[TypeRole]) { - data.insert("type", item.mimeComment()); + data.insert(sharedValue("type"), item.mimeComment()); } } @@ -1961,6 +1961,19 @@ void KFileItemModel::determineMimeTypes(const KFileItemList& items, int timeout) } } +QByteArray KFileItemModel::sharedValue(const QByteArray& value) +{ + static QSet pool; + const QSet::const_iterator it = pool.constFind(value); + + if (it != pool.constEnd()) { + return *it; + } else { + pool.insert(value); + return value; + } +} + bool KFileItemModel::isConsistent() const { if (m_items.count() != m_itemData.count()) { diff --git a/src/kitemviews/kfileitemmodel.h b/src/kitemviews/kfileitemmodel.h index 1d837cb2a..1d2d8c172 100644 --- a/src/kitemviews/kfileitemmodel.h +++ b/src/kitemviews/kfileitemmodel.h @@ -429,6 +429,12 @@ private: */ static void determineMimeTypes(const KFileItemList& items, int timeout); + /** + * @return Returns a copy of \a value that is implicitly shared + * with other users to save memory. + */ + static QByteArray sharedValue(const QByteArray& value); + /** * Checks if the model's internal data structures are consistent. */ -- 2.47.3