From 18ecbb9b14104e169021f0f245dd84728dceb4e0 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Thu, 14 Nov 2019 10:52:37 +0100 Subject: [PATCH] ProjectExplorer: Speed up FolderNode::addNestedNodes() ... by aggregating the look-up of parent folder nodes. Also make use of this function in the GenericProjectManager. As a test case, I added my whole ~/dev directory with ca 600,000 source files to a generic project. With this patch, the time spent on adding the new nodes to the tree went down from 15 seconds to two seconds. Task-number: QTCREATORBUG-20652 Change-Id: If006bce55924feacc071c38ec7a0292d29c51be1 Reviewed-by: hjk --- .../genericprojectmanager/genericproject.cpp | 4 +++- src/plugins/projectexplorer/projectnodes.cpp | 24 +++++++++++++++++-- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/plugins/genericprojectmanager/genericproject.cpp b/src/plugins/genericprojectmanager/genericproject.cpp index 00b75d006b8..312a9cfb1ea 100644 --- a/src/plugins/genericprojectmanager/genericproject.cpp +++ b/src/plugins/genericprojectmanager/genericproject.cpp @@ -465,12 +465,14 @@ void GenericBuildSystem::refresh(RefreshOptions options) // find the common base directory of all source files FilePath baseDir = findCommonSourceRoot(); + std::vector> fileNodes; for (const QString &f : qAsConst(m_files)) { FileType fileType = FileType::Source; // ### FIXME if (f.endsWith(".qrc")) fileType = FileType::Resource; - newRoot->addNestedNode(std::make_unique(FilePath::fromString(f), fileType), baseDir); + fileNodes.emplace_back(std::make_unique(FilePath::fromString(f), fileType)); } + newRoot->addNestedNodes(std::move(fileNodes), baseDir); newRoot->addNestedNode(std::make_unique(FilePath::fromString(m_filesFileName), FileType::Project)); diff --git a/src/plugins/projectexplorer/projectnodes.cpp b/src/plugins/projectexplorer/projectnodes.cpp index 1424333fcc3..97a4bda4dcd 100644 --- a/src/plugins/projectexplorer/projectnodes.cpp +++ b/src/plugins/projectexplorer/projectnodes.cpp @@ -639,8 +639,28 @@ void FolderNode::addNestedNodes(std::vector > &&files, const Utils::FilePath &overrideBaseDir, const FolderNode::FolderNodeFactory &factory) { - for (std::unique_ptr &f : files) - addNestedNode(std::move(f), overrideBaseDir, factory); + using DirWithNodes = std::pair>>; + std::vector fileNodesPerDir; + for (auto &f : files) { + const Utils::FilePath parentDir = f->filePath().parentDir(); + const auto it = std::lower_bound(fileNodesPerDir.begin(), fileNodesPerDir.end(), parentDir, + [](const DirWithNodes &nad, const Utils::FilePath &dir) { return nad.first < dir; }); + if (it == fileNodesPerDir.end() || it->first < parentDir) { + DirWithNodes dirWithNodes; + dirWithNodes.first = parentDir; + dirWithNodes.second.emplace_back(std::move(f)); + fileNodesPerDir.insert(it, std::move(dirWithNodes)); + } else { + it->second.emplace_back(std::move(f)); + } + } + + for (DirWithNodes &dirWithNodes : fileNodesPerDir) { + FolderNode * const folderNode = recursiveFindOrCreateFolderNode(this, dirWithNodes.first, + overrideBaseDir, factory); + for (auto &f : dirWithNodes.second) + folderNode->addNode(std::move(f)); + } } // "Compress" a tree of foldernodes such that foldernodes with exactly one foldernode as a child