aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/bufferfragment_p.h22
-rw-r--r--src/core/kconfigini.cpp21
-rw-r--r--src/core/kconfigini_p.h4
3 files changed, 43 insertions, 4 deletions
diff --git a/src/core/bufferfragment_p.h b/src/core/bufferfragment_p.h
index e2154a59..a86e2922 100644
--- a/src/core/bufferfragment_p.h
+++ b/src/core/bufferfragment_p.h
@@ -150,6 +150,11 @@ public:
return (other.size() != (int)len || memcmp(d, other.constData(), len) != 0);
}
+ bool operator==(const BufferFragment &other) const
+ {
+ return other.len == len && !memcmp(d, other.d, len);
+ }
+
int indexOf(char c, unsigned int from = 0) const
{
const char *cursor = d + from - 1;
@@ -190,4 +195,21 @@ private:
unsigned int len;
};
+uint qHash(const KConfigIniBackend::BufferFragment &fragment)
+{
+ const uchar *p = reinterpret_cast<const uchar*>(fragment.constData());
+ const int len = fragment.length();
+
+ // This algorithm is copied from qhash.cpp (Qt5 version).
+ // Sadly this code is not accessible from the outside without going through abstraction
+ // layers. Even QByteArray::fromRawData would do an allocation internally...
+ uint h = 0;
+
+ for (int i = 0; i < len; ++i) {
+ h = 31 * h + p[i];
+ }
+
+ return h;
+}
+
#endif
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:
diff --git a/src/core/kconfigini_p.h b/src/core/kconfigini_p.h
index 492e1956..29f61090 100644
--- a/src/core/kconfigini_p.h
+++ b/src/core/kconfigini_p.h
@@ -33,10 +33,10 @@ class KConfigIniBackend : public KConfigBackend
{
Q_OBJECT
private:
- class BufferFragment;
-
QLockFile *lockFile;
+
public:
+ class BufferFragment;
KConfigIniBackend();
~KConfigIniBackend();