diff --git a/clang/include/clang/Tooling/JSONCompilationDatabase.h b/clang/include/clang/Tooling/JSONCompilationDatabase.h --- a/clang/include/clang/Tooling/JSONCompilationDatabase.h +++ b/clang/include/clang/Tooling/JSONCompilationDatabase.h @@ -129,6 +129,8 @@ std::vector AllCommands; FileMatchTrie MatchTrie; + // Cache for `MatchTrie`. + mutable llvm::StringMap MatchCache; std::unique_ptr Database; JSONCommandLineSyntax Syntax; diff --git a/clang/lib/Tooling/JSONCompilationDatabase.cpp b/clang/lib/Tooling/JSONCompilationDatabase.cpp --- a/clang/lib/Tooling/JSONCompilationDatabase.cpp +++ b/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 Commands; getCommands(CommandsRefI->getValue(), Commands); return Commands;