ArcsinX created this revision. Herald added subscribers: cfe-commits, usaxena95, kadircet, ilya-biryukov. Herald added a project: clang.
If there is no record in compile_commands.json, we try to find suitable record with `MatchTrie.findEquivalent()` call. This is very expensive operation with a lot of `llvm::sys::fs::equivalent()` calls in some cases. This patch adds caching for `MatchTrie.findEquivalent()` call result. Example scenario without this patch: - compile_commands.json generated at clangd build (contains ~3000 files).. - it tooks more than 1 second to get compile command for newly created file in the root folder of LLVM project. - we wait for 1 second every time when clangd requests compile command for this file (at file change). Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D83621 Files: clang/include/clang/Tooling/JSONCompilationDatabase.h clang/lib/Tooling/JSONCompilationDatabase.cpp Index: clang/lib/Tooling/JSONCompilationDatabase.cpp =================================================================== --- clang/lib/Tooling/JSONCompilationDatabase.cpp +++ clang/lib/Tooling/JSONCompilationDatabase.cpp @@ -230,14 +230,28 @@ SmallString<128> NativeFilePath; llvm::sys::path::native(FilePath, NativeFilePath); - std::string Error; - llvm::raw_string_ostream ES(Error); - StringRef Match = MatchTrie.findEquivalent(NativeFilePath, ES); - if (Match.empty()) - return {}; - const auto CommandsRefI = IndexByFile.find(Match); - if (CommandsRefI == IndexByFile.end()) - return {}; + // Avoid usage of `MatchTrie` if possible. + auto CommandsRefI = IndexByFile.find(NativeFilePath); + if (CommandsRefI == IndexByFile.end()) { + llvm::StringRef Match; + // Try to get cached value. + auto MatchIt = MatchCache.find(NativeFilePath); + if (MatchIt == MatchCache.end()) { + std::string Error; + llvm::raw_string_ostream ES(Error); + Match = MatchTrie.findEquivalent(NativeFilePath, ES); + // Save into cache even if the match result is empty. + MatchCache[NativeFilePath] = Match; + } else { + // Cached value. + Match = MatchIt->second; + } + if (Match.empty()) + return {}; + CommandsRefI = IndexByFile.find(Match); + if (CommandsRefI == IndexByFile.end()) + return {}; + } std::vector<CompileCommand> Commands; getCommands(CommandsRefI->getValue(), Commands); return Commands; Index: clang/include/clang/Tooling/JSONCompilationDatabase.h =================================================================== --- clang/include/clang/Tooling/JSONCompilationDatabase.h +++ clang/include/clang/Tooling/JSONCompilationDatabase.h @@ -129,6 +129,8 @@ std::vector<CompileCommandRef> AllCommands; FileMatchTrie MatchTrie; + // Cache for `MatchTrie`. + mutable llvm::StringMap<llvm::StringRef> MatchCache; std::unique_ptr<llvm::MemoryBuffer> Database; JSONCommandLineSyntax Syntax;
Index: clang/lib/Tooling/JSONCompilationDatabase.cpp =================================================================== --- clang/lib/Tooling/JSONCompilationDatabase.cpp +++ clang/lib/Tooling/JSONCompilationDatabase.cpp @@ -230,14 +230,28 @@ SmallString<128> NativeFilePath; llvm::sys::path::native(FilePath, NativeFilePath); - std::string Error; - llvm::raw_string_ostream ES(Error); - StringRef Match = MatchTrie.findEquivalent(NativeFilePath, ES); - if (Match.empty()) - return {}; - const auto CommandsRefI = IndexByFile.find(Match); - if (CommandsRefI == IndexByFile.end()) - return {}; + // Avoid usage of `MatchTrie` if possible. + auto CommandsRefI = IndexByFile.find(NativeFilePath); + if (CommandsRefI == IndexByFile.end()) { + llvm::StringRef Match; + // Try to get cached value. + auto MatchIt = MatchCache.find(NativeFilePath); + if (MatchIt == MatchCache.end()) { + std::string Error; + llvm::raw_string_ostream ES(Error); + Match = MatchTrie.findEquivalent(NativeFilePath, ES); + // Save into cache even if the match result is empty. + MatchCache[NativeFilePath] = Match; + } else { + // Cached value. + Match = MatchIt->second; + } + if (Match.empty()) + return {}; + CommandsRefI = IndexByFile.find(Match); + if (CommandsRefI == IndexByFile.end()) + return {}; + } std::vector<CompileCommand> Commands; getCommands(CommandsRefI->getValue(), Commands); return Commands; Index: clang/include/clang/Tooling/JSONCompilationDatabase.h =================================================================== --- clang/include/clang/Tooling/JSONCompilationDatabase.h +++ clang/include/clang/Tooling/JSONCompilationDatabase.h @@ -129,6 +129,8 @@ std::vector<CompileCommandRef> AllCommands; FileMatchTrie MatchTrie; + // Cache for `MatchTrie`. + mutable llvm::StringMap<llvm::StringRef> MatchCache; std::unique_ptr<llvm::MemoryBuffer> Database; JSONCommandLineSyntax Syntax;
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits