From 94c43600852a0d018cb82f46c6549960f182dca8 Mon Sep 17 00:00:00 2001 From: David Schulz Date: Thu, 12 Dec 2024 11:50:31 +0100 Subject: [PATCH] Python: optimize the pip and venv checks Those checks can take an considerable amount of time. So instead of running them the first time we want to check this info run them in the background as soon as we have loaded the python settings. Change-Id: I287acd2a5fd7b053873257238f7dfbaa9cf00170 Reviewed-by: Christian Stenger --- src/plugins/python/pythonsettings.cpp | 17 +++++++++--- src/plugins/python/pythonutils.cpp | 39 ++++++++++++++++----------- 2 files changed, 36 insertions(+), 20 deletions(-) diff --git a/src/plugins/python/pythonsettings.cpp b/src/plugins/python/pythonsettings.cpp index e9fbff36b10..bc6eebc7885 100644 --- a/src/plugins/python/pythonsettings.cpp +++ b/src/plugins/python/pythonsettings.cpp @@ -855,11 +855,18 @@ QString PythonSettings::pylsConfiguration() return settingsInstance->m_pylsConfiguration; } +static void cacheVenvAndPipUsability(const Interpreter &interpreter) +{ + Utils::asyncRun(&venvIsUsable, interpreter.command); + Utils::asyncRun(&pipIsUsable, interpreter.command); +} + void PythonSettings::addInterpreter(const Interpreter &interpreter, bool isDefault) { if (Utils::anyOf(settingsInstance->m_interpreters, Utils::equal(&Interpreter::id, interpreter.id))) return; settingsInstance->m_interpreters.append(interpreter); + cacheVenvAndPipUsability(interpreter); if (isDefault) settingsInstance->m_defaultInterpreterId = interpreter.id; saveSettings(); @@ -1026,8 +1033,12 @@ void PythonSettings::initFromSettings(QtcSettings *settings) const auto [valid, outdatedInterpreters] = Utils::partition(m_interpreters, keepInterpreter); m_interpreters = valid; - if (!settings->value(kitsGeneratedKey, false).toBool()) { - for (const Interpreter &interpreter : m_interpreters) { + const bool kitsGenerated = settings->value(kitsGeneratedKey, false).toBool(); + if (kitsGenerated) + fixupPythonKits(); + for (const Interpreter &interpreter : std::as_const(m_interpreters)) { + cacheVenvAndPipUsability(interpreter); + if (!kitsGenerated) { if (interpreter.autoDetected) { const FilePath &cmd = interpreter.command; if (!cmd.isLocal() || cmd.parentDir().pathAppended("activate").exists()) @@ -1035,8 +1046,6 @@ void PythonSettings::initFromSettings(QtcSettings *settings) } addKitsForInterpreter(interpreter, false); } - } else { - fixupPythonKits(); } for (const Interpreter &outdated : outdatedInterpreters) diff --git a/src/plugins/python/pythonutils.cpp b/src/plugins/python/pythonutils.cpp index 04144a3e41b..efcfc4940a5 100644 --- a/src/plugins/python/pythonutils.cpp +++ b/src/plugins/python/pythonutils.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include @@ -192,31 +193,37 @@ bool isVenvPython(const FilePath &python) return python.parentDir().parentDir().pathAppended("pyvenv.cfg").exists(); } -static bool isUsableHelper(QHash *cache, const QString &keyString, - const QString &commandArg, const FilePath &python) +static bool isUsableHelper( + SynchronizedValue> *cache, + const QString &commandArg, + const FilePath &python) { - auto it = cache->find(python); - if (it == cache->end()) { - const Key key = keyFromString(keyString); - Process process; - process.setCommand({python, {"-m", commandArg, "-h"}}); - process.runBlocking(); - const bool usable = process.result() == ProcessResult::FinishedWithSuccess; - it = cache->insert(python, usable); - } - return *it; + std::optional result; + cache->read([&result, python](const QHash &cache) { + if (auto it = cache.find(python); it != cache.end()) + result = it.value(); + }); + if (result) + return *result; + + Process process; + process.setCommand({python, {"-m", commandArg, "-h"}}); + process.runBlocking(); + const bool usable = process.result() == ProcessResult::FinishedWithSuccess; + cache->writeLocked()->insert(python, usable); + return usable; } bool venvIsUsable(const FilePath &python) { - static QHash cache; - return isUsableHelper(&cache, "pyVenvIsUsable", "venv", python); + static SynchronizedValue> cache; + return isUsableHelper(&cache, "venv", python); } bool pipIsUsable(const FilePath &python) { - static QHash cache; - return isUsableHelper(&cache, "pyPipIsUsable", "pip", python); + static SynchronizedValue> cache; + return isUsableHelper(&cache, "pip", python); } QString pythonVersion(const FilePath &python)