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

Reply via email to