[PATCH] D117529: [clangd][NFC] Cache ClangTidy check globs to speed up createChecks
Nathan James via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Mon Jan 17 17:47:34 PST 2022
njames93 created this revision.
njames93 added a reviewer: sammccall.
Herald added subscribers: usaxena95, kadircet, arphaman.
njames93 requested review of this revision.
Herald added subscribers: cfe-commits, MaskRay, ilya-biryukov.
Herald added a project: clang-tools-extra.
Build a fast factory for creating clang-tidy check lists based off a glob string.
Compile Globs into a BitVector representation that can be used to build a vector of checks without having to consult the glob string. Cache these representations as most invocations will be using the same glob string.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D117529
Files:
clang-tools-extra/clangd/ParsedAST.cpp
Index: clang-tools-extra/clangd/ParsedAST.cpp
===================================================================
--- clang-tools-extra/clangd/ParsedAST.cpp
+++ clang-tools-extra/clangd/ParsedAST.cpp
@@ -10,6 +10,7 @@
#include "../clang-tidy/ClangTidyCheck.h"
#include "../clang-tidy/ClangTidyDiagnosticConsumer.h"
#include "../clang-tidy/ClangTidyModuleRegistry.h"
+#include "../clang-tidy/GlobList.h"
#include "AST.h"
#include "Compiler.h"
#include "Config.h"
@@ -45,6 +46,7 @@
#include "clang/Tooling/CompilationDatabase.h"
#include "clang/Tooling/Syntax/Tokens.h"
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
@@ -282,6 +284,59 @@
}
}
+// Turns a clang-tidy glob list into a BitVector that can be used to build the
+// necessary checks efficiently.
+class CachedFactories {
+ std::vector<std::pair<std::string,
+ std::function<std::unique_ptr<tidy::ClangTidyCheck>(
+ llvm::StringRef, tidy::ClangTidyContext *)>>>
+ AllChecks;
+ std::mutex Guard;
+ llvm::StringMap<llvm::BitVector> CachedGlobs;
+
+ llvm::BitVector &getCachedValue(StringRef CheckGlobString) {
+ std::lock_guard<std::mutex> LG(Guard);
+ auto It = CachedGlobs.find(CheckGlobString);
+ if (It != CachedGlobs.end())
+ return It->getValue();
+ // On the first time we see a glob, we construct the representation and
+ // cache it for the next time. In most projects there would only ever be one
+ // unique Glob.
+ tidy::GlobList Glob(CheckGlobString);
+ llvm::BitVector IsEnabled(AllChecks.size(), false);
+ for (size_t I = 0, E = AllChecks.size(); I != E; ++I) {
+ if (Glob.contains(AllChecks[I].first))
+ IsEnabled.set(I);
+ }
+ return CachedGlobs.insert_or_assign(CheckGlobString, std::move(IsEnabled))
+ .first->getValue();
+ }
+
+public:
+ CachedFactories() {
+ tidy::ClangTidyCheckFactories CTFactories;
+ for (const auto &E : tidy::ClangTidyModuleRegistry::entries())
+ E.instantiate()->addCheckFactories(CTFactories);
+ for (const auto &Item : CTFactories) {
+ AllChecks.emplace_back(Item.getKey(), Item.getValue());
+ }
+ }
+
+ std::vector<std::unique_ptr<tidy::ClangTidyCheck>>
+ createChecks(tidy::ClangTidyContext *Context) {
+ if (!Context->getOptions().Checks)
+ return {};
+ llvm::BitVector &IsEnabled = getCachedValue(*Context->getOptions().Checks);
+ std::vector<std::unique_ptr<tidy::ClangTidyCheck>> Result;
+ Result.reserve(IsEnabled.size());
+ for (unsigned CheckID : IsEnabled.set_bits()) {
+ Result.push_back(
+ AllChecks[CheckID].second(AllChecks[CheckID].first, Context));
+ }
+ return Result;
+ }
+};
+
} // namespace
llvm::Optional<ParsedAST>
@@ -410,15 +465,13 @@
// diagnostics.
if (PreserveDiags) {
trace::Span Tracer("ClangTidyInit");
- tidy::ClangTidyCheckFactories CTFactories;
- for (const auto &E : tidy::ClangTidyModuleRegistry::entries())
- E.instantiate()->addCheckFactories(CTFactories);
+ static CachedFactories Factory;
CTContext.emplace(std::make_unique<tidy::DefaultOptionsProvider>(
tidy::ClangTidyGlobalOptions(), ClangTidyOpts));
CTContext->setDiagnosticsEngine(&Clang->getDiagnostics());
CTContext->setASTContext(&Clang->getASTContext());
CTContext->setCurrentFile(Filename);
- CTChecks = CTFactories.createChecks(CTContext.getPointer());
+ CTChecks = Factory.createChecks(CTContext.getPointer());
llvm::erase_if(CTChecks, [&](const auto &Check) {
return !Check->isLanguageVersionSupported(CTContext->getLangOpts());
});
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D117529.400682.patch
Type: text/x-patch
Size: 3736 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20220118/4001c7a0/attachment-0001.bin>
More information about the cfe-commits
mailing list