diff options
author | Eric Liu <ioeric@google.com> | 2018-10-02 10:43:55 +0000 |
---|---|---|
committer | Eric Liu <ioeric@google.com> | 2018-10-02 10:43:55 +0000 |
commit | 7842148d30d3725fcf927fa3bc1c48ec013ac4e0 (patch) | |
tree | bb09ac597cbfe33e7178da9c6280e7a0f1e8f9d0 /clang-tools-extra/unittests | |
parent | cd2df21b7186035ae9900088a9613426f57b707c (diff) |
[clangd] Cache FS stat() calls when building preamble.linaro-local/ci/tcwg-llvm-kernel-baseline-armv8l-release-stablelinaro-local/ci/tcwg-llvm-kernel-baseline-armv8l-release-nextlinaro-local/ci/tcwg-llvm-kernel-baseline-armv8l-release-ltslinaro-local/ci/tcwg-llvm-kernel-baseline-aarch64-release-nextlinaro-local/ci/llvm-kernel-armv8l-baselinelinaro-local/ci/llvm-kernel-aarch64-baseline
Summary:
The file stats can be reused when preamble is reused (e.g. code
completion). It's safe to assume that cached status is not outdated as we
assume preamble files to remain unchanged.
On real file system, this made code completion ~20% faster on a measured file
(with big preamble). The preamble build time doesn't change much.
Reviewers: sammccall, ilya-biryukov
Reviewed By: sammccall
Subscribers: mgorny, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D52419
Diffstat (limited to 'clang-tools-extra/unittests')
-rw-r--r-- | clang-tools-extra/unittests/clangd/CMakeLists.txt | 1 | ||||
-rw-r--r-- | clang-tools-extra/unittests/clangd/ClangdTests.cpp | 65 | ||||
-rw-r--r-- | clang-tools-extra/unittests/clangd/FSTests.cpp | 46 | ||||
-rw-r--r-- | clang-tools-extra/unittests/clangd/TestFS.cpp | 1 |
4 files changed, 113 insertions, 0 deletions
diff --git a/clang-tools-extra/unittests/clangd/CMakeLists.txt b/clang-tools-extra/unittests/clangd/CMakeLists.txt index a870c2990a9..1c98347be55 100644 --- a/clang-tools-extra/unittests/clangd/CMakeLists.txt +++ b/clang-tools-extra/unittests/clangd/CMakeLists.txt @@ -21,6 +21,7 @@ add_extra_unittest(ClangdTests FileDistanceTests.cpp FileIndexTests.cpp FindSymbolsTests.cpp + FSTests.cpp FuzzyMatchTests.cpp GlobalCompilationDatabaseTests.cpp HeadersTests.cpp diff --git a/clang-tools-extra/unittests/clangd/ClangdTests.cpp b/clang-tools-extra/unittests/clangd/ClangdTests.cpp index ace2cef4b45..21300e906c8 100644 --- a/clang-tools-extra/unittests/clangd/ClangdTests.cpp +++ b/clang-tools-extra/unittests/clangd/ClangdTests.cpp @@ -963,6 +963,71 @@ TEST_F(ClangdVFSTest, ChangedHeaderFromISystem) { Field(&CodeCompletion::Name, "baz"))); } +// Check that running code completion doesn't stat() a bunch of files from the +// preamble again. (They should be using the preamble's stat-cache) +TEST(ClangdTests, PreambleVFSStatCache) { + class ListenStatsFSProvider : public FileSystemProvider { + public: + ListenStatsFSProvider(llvm::StringMap<unsigned> &CountStats) + : CountStats(CountStats) {} + + IntrusiveRefCntPtr<vfs::FileSystem> getFileSystem() override { + class ListenStatVFS : public vfs::ProxyFileSystem { + public: + ListenStatVFS(IntrusiveRefCntPtr<vfs::FileSystem> FS, + llvm::StringMap<unsigned> &CountStats) + : ProxyFileSystem(std::move(FS)), CountStats(CountStats) {} + + llvm::ErrorOr<std::unique_ptr<vfs::File>> + openFileForRead(const Twine &Path) override { + ++CountStats[llvm::sys::path::filename(Path.str())]; + return ProxyFileSystem::openFileForRead(Path); + } + llvm::ErrorOr<vfs::Status> status(const Twine &Path) override { + ++CountStats[llvm::sys::path::filename(Path.str())]; + return ProxyFileSystem::status(Path); + } + + private: + llvm::StringMap<unsigned> &CountStats; + }; + + return IntrusiveRefCntPtr<ListenStatVFS>( + new ListenStatVFS(buildTestFS(Files), CountStats)); + } + + // If relative paths are used, they are resolved with testPath(). + llvm::StringMap<std::string> Files; + llvm::StringMap<unsigned> &CountStats; + }; + + llvm::StringMap<unsigned> CountStats; + ListenStatsFSProvider FS(CountStats); + ErrorCheckingDiagConsumer DiagConsumer; + MockCompilationDatabase CDB; + ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest()); + + auto SourcePath = testPath("foo.cpp"); + auto HeaderPath = testPath("foo.h"); + FS.Files[HeaderPath] = "struct TestSym {};"; + Annotations Code(R"cpp( + #include "foo.h" + + int main() { + TestSy^ + })cpp"); + + runAddDocument(Server, SourcePath, Code.code()); + + EXPECT_EQ(CountStats["foo.h"], 1u); + auto Completions = cantFail(runCodeComplete(Server, SourcePath, Code.point(), + clangd::CodeCompleteOptions())) + .Completions; + EXPECT_EQ(CountStats["foo.h"], 1u); + EXPECT_THAT(Completions, + ElementsAre(Field(&CodeCompletion::Name, "TestSym"))); +} + } // namespace } // namespace clangd } // namespace clang diff --git a/clang-tools-extra/unittests/clangd/FSTests.cpp b/clang-tools-extra/unittests/clangd/FSTests.cpp new file mode 100644 index 00000000000..3b028426016 --- /dev/null +++ b/clang-tools-extra/unittests/clangd/FSTests.cpp @@ -0,0 +1,46 @@ +//===-- FSTests.cpp - File system related tests -----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "FS.h" +#include "TestFS.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +namespace clang { +namespace clangd { +namespace { + +TEST(FSTests, PreambleStatusCache) { + llvm::StringMap<std::string> Files; + Files["x"] = ""; + Files["y"] = ""; + auto FS = buildTestFS(Files); + FS->setCurrentWorkingDirectory(testRoot()); + + PreambleFileStatusCache StatCache; + auto ProduceFS = StatCache.getProducingFS(FS); + EXPECT_TRUE(ProduceFS->openFileForRead("x")); + EXPECT_TRUE(ProduceFS->status("y")); + + EXPECT_TRUE(StatCache.lookup(testPath("x")).hasValue()); + EXPECT_TRUE(StatCache.lookup(testPath("y")).hasValue()); + + vfs::Status S("fake", llvm::sys::fs::UniqueID(0, 0), + std::chrono::system_clock::now(), 0, 0, 1024, + llvm::sys::fs::file_type::regular_file, llvm::sys::fs::all_all); + StatCache.update(*FS, S); + auto ConsumeFS = StatCache.getConsumingFS(FS); + auto Cached = ConsumeFS->status(testPath("fake")); + EXPECT_TRUE(Cached); + EXPECT_EQ(Cached->getName(), S.getName()); +} + +} // namespace +} // namespace clangd +} // namespace clang diff --git a/clang-tools-extra/unittests/clangd/TestFS.cpp b/clang-tools-extra/unittests/clangd/TestFS.cpp index d3112b92278..bc8c5479a93 100644 --- a/clang-tools-extra/unittests/clangd/TestFS.cpp +++ b/clang-tools-extra/unittests/clangd/TestFS.cpp @@ -23,6 +23,7 @@ buildTestFS(llvm::StringMap<std::string> const &Files, llvm::StringMap<time_t> const &Timestamps) { IntrusiveRefCntPtr<vfs::InMemoryFileSystem> MemFS( new vfs::InMemoryFileSystem); + MemFS->setCurrentWorkingDirectory(testRoot()); for (auto &FileAndContents : Files) { StringRef File = FileAndContents.first(); MemFS->addFile( |