From 93c9398cdcf147c5c5e1a89662ffd047e36927ac Mon Sep 17 00:00:00 2001 From: Aleix Pol Date: Thu, 1 Jul 2021 02:50:55 +0200 Subject: Cache global config files Whenever we read a config file, we are first parsing kdeglobalsrc. This caches the parsed entries so that they can be reused as long as it hasn't changed. This reduces the parseConfig calls (which is mostly prominent at early process startup) from 18 to 12 (33%) ksmserver-logout-greeter. This also means there's better cache locality as well as less memory allocated as a lot of objects are shared but I have not measured this. --- src/core/kconfig.cpp | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/core/kconfig.cpp b/src/core/kconfig.cpp index cc3700e1..9b8d2e62 100644 --- a/src/core/kconfig.cpp +++ b/src/core/kconfig.cpp @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -28,6 +29,7 @@ #include #include #include +#include #if KCONFIG_USE_DBUS #include @@ -44,6 +46,14 @@ Q_GLOBAL_STATIC(QStringList, s_globalFiles) // For caching purposes. static QBasicMutex s_globalFilesMutex; Q_GLOBAL_STATIC_WITH_ARGS(QString, sGlobalFileName, (QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + QLatin1String("/kdeglobals"))) +using ParseCacheKey = std::pair; +struct ParseCacheValue { + KEntryMap entries; + QDateTime parseTime; +}; +using ParseCache = QThreadStorage>; +Q_GLOBAL_STATIC(ParseCache, sGlobalParse) + #ifndef Q_OS_WIN static const Qt::CaseSensitivity sPathCaseSensitivity = Qt::CaseSensitive; #else @@ -687,8 +697,25 @@ void KConfigPrivate::parseGlobalFiles() const QStringList globalFiles = getGlobalFiles(); // qDebug() << "parsing global files" << globalFiles; - // TODO: can we cache the values in etc_kderc / other global files - // on a per-application basis? + Q_ASSERT(entryMap.isEmpty()); + const ParseCacheKey key = {globalFiles, locale}; + auto data = sGlobalParse->localData().object(key); + QDateTime newest; + for (const auto &file : globalFiles) { + const auto fileDate = QFileInfo(file).lastModified(); + if (fileDate > newest) { + newest = fileDate; + } + } + if (data) { + if (data->parseTime < newest) { + data = nullptr; + } else { + entryMap = data->entries; + return; + } + } + const QByteArray utf8Locale = locale.toUtf8(); for (const QString &file : globalFiles) { KConfigBackend::ParseOptions parseOpts = KConfigBackend::ParseGlobal | KConfigBackend::ParseExpansions; @@ -701,6 +728,7 @@ void KConfigPrivate::parseGlobalFiles() break; } } + sGlobalParse->localData().insert(key, new ParseCacheValue({entryMap, newest})); } void KConfigPrivate::parseConfigFiles() -- cgit v1.2.1