Skip to content

Commit 35ce741

Browse files
committed
[clangd] Store paths as requested in PreambleStatCache
Underlying FS can store different file names inside the stat response (e.g. symlinks resolved, absolute paths, dots removed). But we store path names as requested inside the preamble, https://github.com/llvm/llvm-project/blob/main/clang/lib/Serialization/ASTWriter.cpp#L1635. This improves cache hit rates from ~30% to 90% in a build system that uses symlinks. Differential Revision: https://reviews.llvm.org/D151185
1 parent 70688e8 commit 35ce741

File tree

3 files changed

+15
-11
lines changed

3 files changed

+15
-11
lines changed

clang-tools-extra/clangd/FS.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "llvm/Support/Path.h"
1212
#include "llvm/Support/VirtualFileSystem.h"
1313
#include <optional>
14+
#include <utility>
1415

1516
namespace clang {
1617
namespace clangd {
@@ -23,9 +24,10 @@ PreambleFileStatusCache::PreambleFileStatusCache(llvm::StringRef MainFilePath){
2324
}
2425

2526
void PreambleFileStatusCache::update(const llvm::vfs::FileSystem &FS,
26-
llvm::vfs::Status S) {
27+
llvm::vfs::Status S,
28+
llvm::StringRef File) {
2729
// Canonicalize path for later lookup, which is usually by absolute path.
28-
llvm::SmallString<32> PathStore(S.getName());
30+
llvm::SmallString<32> PathStore(File);
2931
if (FS.makeAbsolute(PathStore))
3032
return;
3133
llvm::sys::path::remove_dots(PathStore, /*remove_dot_dot=*/true);
@@ -72,14 +74,14 @@ PreambleFileStatusCache::getProducingFS(
7274
// many times (e.g. code completion) and the repeated status call is
7375
// likely to be cached in the underlying file system anyway.
7476
if (auto S = File->get()->status())
75-
StatCache.update(getUnderlyingFS(), std::move(*S));
77+
StatCache.update(getUnderlyingFS(), std::move(*S), Path.str());
7678
return File;
7779
}
7880

7981
llvm::ErrorOr<llvm::vfs::Status> status(const llvm::Twine &Path) override {
8082
auto S = getUnderlyingFS().status(Path);
8183
if (S)
82-
StatCache.update(getUnderlyingFS(), *S);
84+
StatCache.update(getUnderlyingFS(), *S, Path.str());
8385
return S;
8486
}
8587

clang-tools-extra/clangd/FS.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ class PreambleFileStatusCache {
4141
/// corresponds to. The stat for the main file will not be cached.
4242
PreambleFileStatusCache(llvm::StringRef MainFilePath);
4343

44-
void update(const llvm::vfs::FileSystem &FS, llvm::vfs::Status S);
44+
void update(const llvm::vfs::FileSystem &FS, llvm::vfs::Status S,
45+
llvm::StringRef File);
4546

4647
/// \p Path is a path stored in preamble.
4748
std::optional<llvm::vfs::Status> lookup(llvm::StringRef Path) const;

clang-tools-extra/clangd/unittests/FSTests.cpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,18 +37,19 @@ TEST(FSTests, PreambleStatusCache) {
3737
std::chrono::system_clock::now(), 0, 0, 1024,
3838
llvm::sys::fs::file_type::regular_file,
3939
llvm::sys::fs::all_all);
40-
StatCache.update(*FS, S);
40+
StatCache.update(*FS, S, "real");
4141
auto ConsumeFS = StatCache.getConsumingFS(FS);
42-
auto Cached = ConsumeFS->status(testPath("fake"));
42+
EXPECT_FALSE(ConsumeFS->status(testPath("fake")));
43+
auto Cached = ConsumeFS->status(testPath("real"));
4344
EXPECT_TRUE(Cached);
44-
EXPECT_EQ(Cached->getName(), testPath("fake"));
45+
EXPECT_EQ(Cached->getName(), testPath("real"));
4546
EXPECT_EQ(Cached->getUniqueID(), S.getUniqueID());
4647

47-
// fake and temp/../fake should hit the same cache entry.
48+
// real and temp/../real should hit the same cache entry.
4849
// However, the Status returned reflects the actual path requested.
49-
auto CachedDotDot = ConsumeFS->status(testPath("temp/../fake"));
50+
auto CachedDotDot = ConsumeFS->status(testPath("temp/../real"));
5051
EXPECT_TRUE(CachedDotDot);
51-
EXPECT_EQ(CachedDotDot->getName(), testPath("temp/../fake"));
52+
EXPECT_EQ(CachedDotDot->getName(), testPath("temp/../real"));
5253
EXPECT_EQ(CachedDotDot->getUniqueID(), S.getUniqueID());
5354
}
5455

0 commit comments

Comments
 (0)