Clang: Reduce database accesses

If we prefetch data from the database to the caches we reduce the database
transaction calls which are quite expensive.

Change-Id: I617a0d886807402e0a94291a913a77f989970b55
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
Marco Bubke
2019-08-20 14:45:01 +02:00
parent 04f8ff6404
commit c174eb378a
47 changed files with 617 additions and 213 deletions

View File

@@ -46,8 +46,11 @@
#include <utils/algorithm.h>
#include <utils/namevalueitem.h>
#include <QDirIterator>
#include <algorithm>
#include <functional>
#include <iostream>
namespace ClangPchManager {
@@ -68,6 +71,7 @@ void ProjectUpdater::updateProjectParts(const std::vector<CppTools::ProjectPart
Utils::SmallStringVector &&toolChainArguments)
{
addProjectFilesToFilePathCache(projectParts);
fetchProjectPartIds(projectParts);
m_server.updateProjectParts(
ClangBackEnd::UpdateProjectPartsMessage{toProjectPartContainers(projectParts),
@@ -237,7 +241,7 @@ void updateWithSettings(ClangBackEnd::CompilerMacros &macros,
} // namespace
ClangBackEnd::CompilerMacros ProjectUpdater::createCompilerMacros(
const ProjectExplorer::Macros &projectMacros, Utils::NameValueItems &&settingsMacros) const
const ProjectExplorer::Macros &projectMacros, Utils::NameValueItems &&settingsMacros)
{
int index = 0;
auto macros = Utils::transform<ClangBackEnd::CompilerMacros>(
@@ -347,10 +351,10 @@ ClangBackEnd::ProjectPartContainer ProjectUpdater::toProjectPartContainer(
auto includeSearchPaths = createIncludeSearchPaths(*projectPart);
const QByteArray projectPartName = projectPart->id().toUtf8();
ClangBackEnd::ProjectPartId projectPartId = m_projectPartsStorage.fetchProjectPartId(
projectPartName);
ClangBackEnd::ProjectPartId projectPartId = m_projectPartIdCache.stringId(
Utils::PathString{projectPart->id()}, [&](Utils::SmallStringView projectPartName) {
return m_projectPartsStorage.fetchProjectPartId(projectPartName);
});
ClangIndexingProjectSettings *settings = m_settingsManager.settings(projectPart->project);
@@ -415,36 +419,31 @@ ClangBackEnd::FilePaths ProjectUpdater::createExcludedPaths(
QString ProjectUpdater::fetchProjectPartName(ClangBackEnd::ProjectPartId projectPartId) const
{
return m_projectPartsStorage.fetchProjectPartName(projectPartId).toQString();
return QString(m_projectPartIdCache.string(projectPartId.projectPathId,
[&](ClangBackEnd::ProjectPartId projectPartId) {
return m_projectPartsStorage.fetchProjectPartName(
projectPartId);
}));
}
ClangBackEnd::ProjectPartIds ProjectUpdater::toProjectPartIds(
const QStringList &projectPartNames) const
const QStringList &projectPartNamesAsQString) const
{
ClangBackEnd::ProjectPartIds projectPartIds;
projectPartIds.reserve(projectPartIds.size());
std::transform(projectPartNames.begin(),
projectPartNames.end(),
std::back_inserter(projectPartIds),
[&](const QString &projectPartName) {
return m_projectPartsStorage.fetchProjectPartId(
Utils::SmallString{projectPartName});
});
auto projectPartNames = Utils::transform<std::vector<Utils::PathString>>(
projectPartNamesAsQString, [&](const QString &projectPartName) { return projectPartName; });
return projectPartIds;
return m_projectPartIdCache.stringIds(projectPartNames, [&](Utils::SmallStringView projectPartName) {
return m_projectPartsStorage.fetchProjectPartId(projectPartName);
});
}
void ProjectUpdater::addProjectFilesToFilePathCache(const std::vector<CppTools::ProjectPart *> &projectParts)
{
std::size_t fileCount = std::accumulate(projectParts.begin(),
projectParts.end(),
std::size_t(0),
[](std::size_t value, CppTools::ProjectPart *projectPart) {
return value + std::size_t(projectPart->files.size());
});
ClangBackEnd::FilePaths filePaths;
filePaths.reserve(fileCount);
filePaths.reserve(10000);
for (CppTools::ProjectPart *projectPart : projectParts) {
for (const CppTools::ProjectFile &file : projectPart->files)
@@ -455,4 +454,28 @@ void ProjectUpdater::addProjectFilesToFilePathCache(const std::vector<CppTools::
m_filePathCache.addFilePaths(filePaths);
}
void ProjectUpdater::fetchProjectPartIds(const std::vector<CppTools::ProjectPart *> &projectParts)
{
std::unique_ptr<Sqlite::DeferredTransaction> transaction;
auto projectPartNames = Utils::transform<std::vector<Utils::PathString>>(
projectParts, [](CppTools::ProjectPart *projectPart) { return projectPart->id(); });
auto projectPartNameViews = Utils::transform<std::vector<Utils::SmallStringView>>(
projectPartNames,
[](const Utils::PathString &projectPartName) { return projectPartName.toStringView(); });
m_projectPartIdCache
.addStrings(std::move(projectPartNameViews), [&](Utils::SmallStringView projectPartName) {
if (!transaction)
transaction = std::make_unique<Sqlite::DeferredTransaction>(
m_projectPartsStorage.transactionBackend());
return m_projectPartsStorage.fetchProjectPartIdUnguarded(projectPartName);
});
if (transaction)
transaction->commit();
} // namespace ClangPchManager
} // namespace ClangPchManager

View File

@@ -34,6 +34,8 @@
#include <includesearchpath.h>
#include <projectpartcontainer.h>
#include <projectpartsstorageinterface.h>
#include <projectpartstoragestructs.h>
#include <stringcache.h>
#include <projectexplorer/headerpath.h>
@@ -66,6 +68,14 @@ class ClangIndexingProjectSettings;
class CLANGPCHMANAGER_EXPORT ProjectUpdater
{
using StringCache = ClangBackEnd::StringCache<Utils::PathString,
Utils::SmallStringView,
ClangBackEnd::ProjectPartId,
ClangBackEnd::NonLockingMutex,
decltype(&Utils::reverseCompare),
Utils::reverseCompare,
ClangBackEnd::Internal::ProjectPartNameId>;
public:
struct SystemAndProjectIncludeSearchPaths
{
@@ -77,11 +87,13 @@ public:
ClangBackEnd::FilePathCachingInterface &filePathCache,
ClangBackEnd::ProjectPartsStorageInterface &projectPartsStorage,
ClangIndexingSettingsManager &settingsManager)
: m_server(server)
, m_filePathCache(filePathCache)
: m_filePathCache(filePathCache)
, m_server(server)
, m_projectPartsStorage(projectPartsStorage)
, m_settingsManager(settingsManager)
{}
{
m_projectPartIdCache.populate(m_projectPartsStorage.fetchAllProjectPartNamesAndIds());
}
void updateProjectParts(const std::vector<CppTools::ProjectPart *> &projectParts,
Utils::SmallStringVector &&toolChainArguments);
@@ -104,8 +116,8 @@ public:
void addToHeaderAndSources(HeaderAndSources &headerAndSources,
const CppTools::ProjectFile &projectFile) const;
static QStringList toolChainArguments(CppTools::ProjectPart *projectPart);
ClangBackEnd::CompilerMacros createCompilerMacros(const ProjectExplorer::Macros &projectMacros,
Utils::NameValueItems &&settingsMacros) const;
static ClangBackEnd::CompilerMacros createCompilerMacros(const ProjectExplorer::Macros &projectMacros,
Utils::NameValueItems &&settingsMacros);
static SystemAndProjectIncludeSearchPaths createIncludeSearchPaths(
const CppTools::ProjectPart &projectPart);
static ClangBackEnd::FilePaths createExcludedPaths(
@@ -115,16 +127,19 @@ public:
ClangBackEnd::ProjectPartIds toProjectPartIds(const QStringList &projectPartNames) const;
private:
void addProjectFilesToFilePathCache(const std::vector<CppTools::ProjectPart *> &projectParts);
void fetchProjectPartIds(const std::vector<CppTools::ProjectPart *> &projectParts);
protected:
ClangBackEnd::FilePathCachingInterface &m_filePathCache;
private:
ClangBackEnd::GeneratedFiles m_generatedFiles;
ClangBackEnd::FilePaths m_excludedPaths;
ClangBackEnd::ProjectManagementServerInterface &m_server;
ClangBackEnd::FilePathCachingInterface &m_filePathCache;
ClangBackEnd::ProjectPartsStorageInterface &m_projectPartsStorage;
ClangIndexingSettingsManager &m_settingsManager;
mutable StringCache m_projectPartIdCache;
};
} // namespace ClangPchManager

View File

@@ -29,6 +29,8 @@
#include <projectexplorer/project.h>
#include <filepathcachinginterface.h>
namespace ClangPchManager {
namespace Internal {
@@ -38,16 +40,21 @@ CppTools::CppModelManager *cppModelManager()
return CppTools::CppModelManager::instance();
}
std::vector<ClangBackEnd::V2::FileContainer> createGeneratedFiles()
std::vector<ClangBackEnd::V2::FileContainer> createGeneratedFiles(
ClangBackEnd::FilePathCachingInterface &filePathCache)
{
auto abstractEditors = CppTools::CppModelManager::instance()->abstractEditorSupports();
std::vector<ClangBackEnd::V2::FileContainer> generatedFiles;
generatedFiles.reserve(std::size_t(abstractEditors.size()));
auto toFileContainer = [] (const CppTools::AbstractEditorSupport *abstractEditor) {
return ClangBackEnd::V2::FileContainer(ClangBackEnd::FilePath(abstractEditor->fileName()),
Utils::SmallString::fromQByteArray(abstractEditor->contents()),
{});
auto toFileContainer = [&](const CppTools::AbstractEditorSupport *abstractEditor) {
ClangBackEnd::FilePath filePath(abstractEditor->fileName());
ClangBackEnd::FilePathId filePathId = filePathCache.filePathId(filePath);
return ClangBackEnd::V2::FileContainer(std::move(filePath),
filePathId,
Utils::SmallString::fromQByteArray(
abstractEditor->contents()),
{});
};
std::transform(abstractEditors.begin(),

View File

@@ -32,6 +32,8 @@
#include <filecontainerv2.h>
#include <utils/algorithm.h>
#include <QObject>
namespace ProjectExplorer {
@@ -46,7 +48,8 @@ namespace ClangPchManager {
namespace Internal {
CLANGPCHMANAGER_EXPORT CppTools::CppModelManager *cppModelManager();
CLANGPCHMANAGER_EXPORT std::vector<ClangBackEnd::V2::FileContainer> createGeneratedFiles();
CLANGPCHMANAGER_EXPORT std::vector<ClangBackEnd::V2::FileContainer> createGeneratedFiles(
ClangBackEnd::FilePathCachingInterface &filePathCache);
CLANGPCHMANAGER_EXPORT std::vector<CppTools::ProjectPart*> createProjectParts(ProjectExplorer::Project *project);
}
@@ -83,9 +86,13 @@ public:
ProjectUpdaterType::removeProjectParts(projectPartIds);
}
void abstractEditorUpdated(const QString &filePath, const QByteArray &contents)
void abstractEditorUpdated(const QString &qFilePath, const QByteArray &contents)
{
ProjectUpdaterType::updateGeneratedFiles({{ClangBackEnd::FilePath{filePath}, contents}});
ClangBackEnd::FilePath filePath{qFilePath};
ClangBackEnd::FilePathId filePathId = ProjectUpdaterType::m_filePathCache.filePathId(
filePath);
ProjectUpdaterType::updateGeneratedFiles({{std::move(filePath), filePathId, contents}});
}
void abstractEditorRemoved(const QString &filePath)
@@ -98,6 +105,14 @@ protected:
const Utils::FilePath &,
const Utils::FilePathList &targets) override
{
auto filePaths = Utils::transform<ClangBackEnd::FilePaths>(targets,
[](const Utils::FilePath &filePath) {
return ClangBackEnd::FilePath{
filePath.toString()};
});
ProjectUpdater::m_filePathCache.addFilePaths(filePaths);
for (const Utils::FilePath &target : targets)
abstractEditorUpdated(target.toString(), {});
}
@@ -105,7 +120,8 @@ protected:
private:
void connectToCppModelManager()
{
ProjectUpdaterType::updateGeneratedFiles(Internal::createGeneratedFiles());
ProjectUpdaterType::updateGeneratedFiles(
Internal::createGeneratedFiles(ProjectUpdaterType::m_filePathCache));
QObject::connect(Internal::cppModelManager(),
&CppTools::CppModelManager::projectPartsUpdated,