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 <hjk@qt.io>
This commit is contained in:
Christian Kandeler
2019-11-14 10:52:37 +01:00
parent b1ea9bad7f
commit 18ecbb9b14
2 changed files with 25 additions and 3 deletions

View File

@@ -465,12 +465,14 @@ void GenericBuildSystem::refresh(RefreshOptions options)
// find the common base directory of all source files
FilePath baseDir = findCommonSourceRoot();
std::vector<std::unique_ptr<FileNode>> 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<FileNode>(FilePath::fromString(f), fileType), baseDir);
fileNodes.emplace_back(std::make_unique<FileNode>(FilePath::fromString(f), fileType));
}
newRoot->addNestedNodes(std::move(fileNodes), baseDir);
newRoot->addNestedNode(std::make_unique<FileNode>(FilePath::fromString(m_filesFileName),
FileType::Project));

View File

@@ -639,8 +639,28 @@ void FolderNode::addNestedNodes(std::vector<std::unique_ptr<FileNode> > &&files,
const Utils::FilePath &overrideBaseDir,
const FolderNode::FolderNodeFactory &factory)
{
for (std::unique_ptr<FileNode> &f : files)
addNestedNode(std::move(f), overrideBaseDir, factory);
using DirWithNodes = std::pair<Utils::FilePath, std::vector<std::unique_ptr<FileNode>>>;
std::vector<DirWithNodes> 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