[PATCH] D83621: [clang][Tooling] Try to avoid file system access if there is no record for the file in compile_commads.json

Aleksandr Platonov via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Sat Jul 11 06:05:05 PDT 2020


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;


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D83621.277235.patch
Type: text/x-patch
Size: 2003 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20200711/4d673c3f/attachment.bin>


More information about the cfe-commits mailing list