aboutsummaryrefslogtreecommitdiff
path: root/src/core/kconfigini.cpp
diff options
context:
space:
mode:
authorMilian Wolff <mail@milianw.de>2014-06-19 12:21:41 +0200
committerMilian Wolff <mail@milianw.de>2014-06-19 12:21:41 +0200
commit9aeacb07b1169fa3dc9b7653e8f30070a91569d5 (patch)
tree711b513326fb9c459a8b9a6fb7e64517e2022351 /src/core/kconfigini.cpp
parent9a5d6523689067a9cde717a8f375d4eca246b119 (diff)
downloadkconfig-9aeacb07b1169fa3dc9b7653e8f30070a91569d5.tar.gz
kconfig-9aeacb07b1169fa3dc9b7653e8f30070a91569d5.tar.bz2
Optimize KConfigIniBackend::parseConfig by reducing allocations.
Yet another awesome application of the Qt implicit sharing trick. Since config files often contain only few different keys and even value strings, we can share them. This reduces memory consumption and also speeds up parsing, as we do not have to allocate the duplicated strings, but can simply reuse the previous values. The most extreme case for this of my knowledge, is KatePart: katesyntaxhighlightingrc has more than 20k lines which triggered nearly 30k allocations on startup. With this patch applied, this value goes down dramatically. I added a simple static counter for the cache hit/miss ratio, which resulted in 5442 cache misses compared to 43624 cache hits across all KConfig files parsed by kwrite. REVIEW: 118587 This is a forward-port of b8aaeff128233cfaecf67899168887572589dde8.
Diffstat (limited to 'src/core/kconfigini.cpp')
-rw-r--r--src/core/kconfigini.cpp21
1 files changed, 19 insertions, 2 deletions
diff --git a/src/core/kconfigini.cpp b/src/core/kconfigini.cpp
index a882ee31..f4ce9410 100644
--- a/src/core/kconfigini.cpp
+++ b/src/core/kconfigini.cpp
@@ -44,6 +44,15 @@
KCONFIGCORE_EXPORT bool kde_kiosk_exception = false; // flag to disable kiosk restrictions
+static QByteArray lookup(const KConfigIniBackend::BufferFragment &fragment, QHash<KConfigIniBackend::BufferFragment, QByteArray> *cache)
+{
+ QHash<KConfigIniBackend::BufferFragment, QByteArray>::iterator it = cache->find(fragment);
+ if (it == cache->end()) {
+ it = cache->insert(fragment, fragment.toByteArray());
+ }
+ return it.value();
+}
+
QString KConfigIniBackend::warningProlog(const QFile &file, int line)
{
return QString::fromLatin1("KConfigIni: In file %2, line %1: ")
@@ -100,6 +109,14 @@ KConfigIniBackend::parseConfig(const QByteArray &currentLocale, KEntryMap &entry
unsigned int len = contents.length();
unsigned int startOfLine = 0;
+ // Reduce memory overhead by making use of implicit sharing
+ // This assumes that config files contain only a small amount of
+ // different fragments which are repeated often.
+ // This is often the case, especially sub groups will all have
+ // the same list of keys and similar values as well.
+ QHash<BufferFragment, QByteArray> cache;
+ cache.reserve(4096);
+
while (startOfLine < len) {
BufferFragment line = contents.split('\n', &startOfLine);
line.trim();
@@ -265,9 +282,9 @@ KConfigIniBackend::parseConfig(const QByteArray &currentLocale, KEntryMap &entry
rawKey.reserve(aKey.length() + locale.length() + 2);
rawKey.append(aKey.toVolatileByteArray());
rawKey.append('[').append(locale.toVolatileByteArray()).append(']');
- entryMap.setEntry(currentGroup, rawKey, line.toByteArray(), entryOptions);
+ entryMap.setEntry(currentGroup, rawKey, lookup(line, &cache), entryOptions);
} else {
- entryMap.setEntry(currentGroup, aKey.toByteArray(), line.toByteArray(), entryOptions);
+ entryMap.setEntry(currentGroup, lookup(aKey, &cache), lookup(line, &cache), entryOptions);
}
}
next_line: