[clang-tools-extra] r343576 - [clangd] Cache FS stat() calls when building preamble.
Mikael Holmén via cfe-commits
cfe-commits at lists.llvm.org
Tue Oct 2 23:00:46 PDT 2018
Hi Eric,
I fixed a compilation warning introduced with this patch in r343661.
Regards,
Mikael
On 10/02/2018 12:43 PM, Eric Liu via cfe-commits wrote:
> Author: ioeric
> Date: Tue Oct 2 03:43:55 2018
> New Revision: 343576
>
> URL: http://llvm.org/viewvc/llvm-project?rev=343576&view=rev
> Log:
> [clangd] Cache FS stat() calls when building preamble.
>
> 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
>
> Added:
> clang-tools-extra/trunk/clangd/FS.cpp
> clang-tools-extra/trunk/clangd/FS.h
> clang-tools-extra/trunk/unittests/clangd/FSTests.cpp
> Modified:
> clang-tools-extra/trunk/clangd/CMakeLists.txt
> clang-tools-extra/trunk/clangd/ClangdServer.cpp
> clang-tools-extra/trunk/clangd/ClangdUnit.cpp
> clang-tools-extra/trunk/clangd/ClangdUnit.h
> clang-tools-extra/trunk/clangd/CodeComplete.cpp
> clang-tools-extra/trunk/clangd/CodeComplete.h
> clang-tools-extra/trunk/unittests/clangd/CMakeLists.txt
> clang-tools-extra/trunk/unittests/clangd/ClangdTests.cpp
> clang-tools-extra/trunk/unittests/clangd/TestFS.cpp
>
> Modified: clang-tools-extra/trunk/clangd/CMakeLists.txt
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/CMakeLists.txt?rev=343576&r1=343575&r2=343576&view=diff
> ==============================================================================
> --- clang-tools-extra/trunk/clangd/CMakeLists.txt (original)
> +++ clang-tools-extra/trunk/clangd/CMakeLists.txt Tue Oct 2 03:43:55 2018
> @@ -21,6 +21,7 @@ add_clang_library(clangDaemon
> DraftStore.cpp
> FindSymbols.cpp
> FileDistance.cpp
> + FS.cpp
> FuzzyMatch.cpp
> GlobalCompilationDatabase.cpp
> Headers.cpp
>
> Modified: clang-tools-extra/trunk/clangd/ClangdServer.cpp
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdServer.cpp?rev=343576&r1=343575&r2=343576&view=diff
> ==============================================================================
> --- clang-tools-extra/trunk/clangd/ClangdServer.cpp (original)
> +++ clang-tools-extra/trunk/clangd/ClangdServer.cpp Tue Oct 2 03:43:55 2018
> @@ -181,8 +181,6 @@ void ClangdServer::codeComplete(PathRef
> if (isCancelled())
> return CB(llvm::make_error<CancelledError>());
>
> - auto PreambleData = IP->Preamble;
> -
> llvm::Optional<SpeculativeFuzzyFind> SpecFuzzyFind;
> if (CodeCompleteOpts.Index && CodeCompleteOpts.SpeculativeIndexRequest) {
> SpecFuzzyFind.emplace();
> @@ -195,10 +193,8 @@ void ClangdServer::codeComplete(PathRef
> // FIXME(ibiryukov): even if Preamble is non-null, we may want to check
> // both the old and the new version in case only one of them matches.
> CodeCompleteResult Result = clangd::codeComplete(
> - File, IP->Command, PreambleData ? &PreambleData->Preamble : nullptr,
> - PreambleData ? PreambleData->Includes : IncludeStructure(),
> - IP->Contents, Pos, FS, PCHs, CodeCompleteOpts,
> - SpecFuzzyFind ? SpecFuzzyFind.getPointer() : nullptr);
> + File, IP->Command, IP->Preamble, IP->Contents, Pos, FS, PCHs,
> + CodeCompleteOpts, SpecFuzzyFind ? SpecFuzzyFind.getPointer() : nullptr);
> {
> clang::clangd::trace::Span Tracer("Completion results callback");
> CB(std::move(Result));
> @@ -231,9 +227,8 @@ void ClangdServer::signatureHelp(PathRef
> return CB(IP.takeError());
>
> auto PreambleData = IP->Preamble;
> - CB(clangd::signatureHelp(File, IP->Command,
> - PreambleData ? &PreambleData->Preamble : nullptr,
> - IP->Contents, Pos, FS, PCHs, Index));
> + CB(clangd::signatureHelp(File, IP->Command, PreambleData, IP->Contents, Pos,
> + FS, PCHs, Index));
> };
>
> // Unlike code completion, we wait for an up-to-date preamble here.
>
> Modified: clang-tools-extra/trunk/clangd/ClangdUnit.cpp
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdUnit.cpp?rev=343576&r1=343575&r2=343576&view=diff
> ==============================================================================
> --- clang-tools-extra/trunk/clangd/ClangdUnit.cpp (original)
> +++ clang-tools-extra/trunk/clangd/ClangdUnit.cpp Tue Oct 2 03:43:55 2018
> @@ -246,9 +246,10 @@ const IncludeStructure &ParsedAST::getIn
> }
>
> PreambleData::PreambleData(PrecompiledPreamble Preamble,
> - std::vector<Diag> Diags, IncludeStructure Includes)
> + std::vector<Diag> Diags, IncludeStructure Includes,
> + std::unique_ptr<PreambleFileStatusCache> StatCache)
> : Preamble(std::move(Preamble)), Diags(std::move(Diags)),
> - Includes(std::move(Includes)) {}
> + Includes(std::move(Includes)), StatCache(std::move(StatCache)) {}
>
> ParsedAST::ParsedAST(std::shared_ptr<const PreambleData> Preamble,
> std::unique_ptr<CompilerInstance> Clang,
> @@ -334,9 +335,12 @@ std::shared_ptr<const PreambleData> clan
> // We proceed anyway, our lit-tests rely on results for non-existing working
> // dirs.
> }
> +
> + auto StatCache = llvm::make_unique<PreambleFileStatusCache>();
> auto BuiltPreamble = PrecompiledPreamble::Build(
> - CI, ContentsBuffer.get(), Bounds, *PreambleDiagsEngine, Inputs.FS, PCHs,
> - StoreInMemory, SerializedDeclsCollector);
> + CI, ContentsBuffer.get(), Bounds, *PreambleDiagsEngine,
> + StatCache->getProducingFS(Inputs.FS), PCHs, StoreInMemory,
> + SerializedDeclsCollector);
>
> // When building the AST for the main file, we do want the function
> // bodies.
> @@ -347,7 +351,7 @@ std::shared_ptr<const PreambleData> clan
> FileName);
> return std::make_shared<PreambleData>(
> std::move(*BuiltPreamble), PreambleDiagnostics.take(),
> - SerializedDeclsCollector.takeIncludes());
> + SerializedDeclsCollector.takeIncludes(), std::move(StatCache));
> } else {
> elog("Could not build a preamble for file {0}", FileName);
> return nullptr;
> @@ -361,15 +365,19 @@ llvm::Optional<ParsedAST> clangd::buildA
> trace::Span Tracer("BuildAST");
> SPAN_ATTACH(Tracer, "File", FileName);
>
> - if (Inputs.FS->setCurrentWorkingDirectory(Inputs.CompileCommand.Directory)) {
> + auto VFS = Inputs.FS;
> + if (Preamble && Preamble->StatCache)
> + VFS = Preamble->StatCache->getConsumingFS(std::move(VFS));
> + if (VFS->setCurrentWorkingDirectory(Inputs.CompileCommand.Directory)) {
> log("Couldn't set working directory when building the preamble.");
> // We proceed anyway, our lit-tests rely on results for non-existing working
> // dirs.
> }
>
> - return ParsedAST::build(
> - llvm::make_unique<CompilerInvocation>(*Invocation), Preamble,
> - llvm::MemoryBuffer::getMemBufferCopy(Inputs.Contents), PCHs, Inputs.FS);
> + return ParsedAST::build(llvm::make_unique<CompilerInvocation>(*Invocation),
> + Preamble,
> + llvm::MemoryBuffer::getMemBufferCopy(Inputs.Contents),
> + PCHs, std::move(VFS));
> }
>
> SourceLocation clangd::getBeginningOfIdentifier(ParsedAST &Unit,
>
> Modified: clang-tools-extra/trunk/clangd/ClangdUnit.h
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdUnit.h?rev=343576&r1=343575&r2=343576&view=diff
> ==============================================================================
> --- clang-tools-extra/trunk/clangd/ClangdUnit.h (original)
> +++ clang-tools-extra/trunk/clangd/ClangdUnit.h Tue Oct 2 03:43:55 2018
> @@ -11,6 +11,7 @@
> #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_CLANGDUNIT_H
>
> #include "Diagnostics.h"
> +#include "FS.h"
> #include "Function.h"
> #include "Headers.h"
> #include "Path.h"
> @@ -45,7 +46,8 @@ namespace clangd {
> // Stores Preamble and associated data.
> struct PreambleData {
> PreambleData(PrecompiledPreamble Preamble, std::vector<Diag> Diags,
> - IncludeStructure Includes);
> + IncludeStructure Includes,
> + std::unique_ptr<PreambleFileStatusCache> StatCache);
>
> tooling::CompileCommand CompileCommand;
> PrecompiledPreamble Preamble;
> @@ -53,6 +55,9 @@ struct PreambleData {
> // Processes like code completions and go-to-definitions will need #include
> // information, and their compile action skips preamble range.
> IncludeStructure Includes;
> + // Cache of FS operations performed when building the preamble.
> + // When reusing a preamble, this cache can be consumed to save IO.
> + std::unique_ptr<PreambleFileStatusCache> StatCache;
> };
>
> /// Information required to run clang, e.g. to parse AST or do code completion.
>
> Modified: clang-tools-extra/trunk/clangd/CodeComplete.cpp
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/CodeComplete.cpp?rev=343576&r1=343575&r2=343576&view=diff
> ==============================================================================
> --- clang-tools-extra/trunk/clangd/CodeComplete.cpp (original)
> +++ clang-tools-extra/trunk/clangd/CodeComplete.cpp Tue Oct 2 03:43:55 2018
> @@ -20,6 +20,7 @@
>
> #include "CodeComplete.h"
> #include "AST.h"
> +#include "ClangdUnit.h"
> #include "CodeCompletionStrings.h"
> #include "Compiler.h"
> #include "Diagnostics.h"
> @@ -986,7 +987,7 @@ private:
> struct SemaCompleteInput {
> PathRef FileName;
> const tooling::CompileCommand &Command;
> - PrecompiledPreamble const *Preamble;
> + const PreambleData *Preamble;
> StringRef Contents;
> Position Pos;
> IntrusiveRefCntPtr<vfs::FileSystem> VFS;
> @@ -1010,12 +1011,15 @@ bool semaCodeComplete(std::unique_ptr<Co
> // working dirs.
> }
>
> + IntrusiveRefCntPtr<vfs::FileSystem> VFS = Input.VFS;
> + if (Input.Preamble && Input.Preamble->StatCache)
> + VFS = Input.Preamble->StatCache->getConsumingFS(std::move(VFS));
> IgnoreDiagnostics DummyDiagsConsumer;
> auto CI = createInvocationFromCommandLine(
> ArgStrs,
> CompilerInstance::createDiagnostics(new DiagnosticOptions,
> &DummyDiagsConsumer, false),
> - Input.VFS);
> + VFS);
> if (!CI) {
> elog("Couldn't create CompilerInvocation");
> return false;
> @@ -1054,8 +1058,10 @@ bool semaCodeComplete(std::unique_ptr<Co
> // NOTE: we must call BeginSourceFile after prepareCompilerInstance. Otherwise
> // the remapped buffers do not get freed.
> auto Clang = prepareCompilerInstance(
> - std::move(CI), CompletingInPreamble ? nullptr : Input.Preamble,
> - std::move(ContentsBuffer), std::move(Input.PCHs), std::move(Input.VFS),
> + std::move(CI),
> + (Input.Preamble && !CompletingInPreamble) ? &Input.Preamble->Preamble
> + : nullptr,
> + std::move(ContentsBuffer), std::move(Input.PCHs), std::move(VFS),
> DummyDiagsConsumer);
> Clang->getPreprocessorOpts().SingleFileParseMode = CompletingInPreamble;
> Clang->setCodeCompletionConsumer(Consumer.release());
> @@ -1565,19 +1571,20 @@ speculateCompletionFilter(llvm::StringRe
>
> CodeCompleteResult
> codeComplete(PathRef FileName, const tooling::CompileCommand &Command,
> - PrecompiledPreamble const *Preamble,
> - const IncludeStructure &PreambleInclusions, StringRef Contents,
> - Position Pos, IntrusiveRefCntPtr<vfs::FileSystem> VFS,
> + const PreambleData *Preamble, StringRef Contents, Position Pos,
> + IntrusiveRefCntPtr<vfs::FileSystem> VFS,
> std::shared_ptr<PCHContainerOperations> PCHs,
> CodeCompleteOptions Opts, SpeculativeFuzzyFind *SpecFuzzyFind) {
> - return CodeCompleteFlow(FileName, PreambleInclusions, SpecFuzzyFind, Opts)
> + return CodeCompleteFlow(FileName,
> + Preamble ? Preamble->Includes : IncludeStructure(),
> + SpecFuzzyFind, Opts)
> .run({FileName, Command, Preamble, Contents, Pos, VFS, PCHs});
> }
>
> SignatureHelp signatureHelp(PathRef FileName,
> const tooling::CompileCommand &Command,
> - PrecompiledPreamble const *Preamble,
> - StringRef Contents, Position Pos,
> + const PreambleData *Preamble, StringRef Contents,
> + Position Pos,
> IntrusiveRefCntPtr<vfs::FileSystem> VFS,
> std::shared_ptr<PCHContainerOperations> PCHs,
> const SymbolIndex *Index) {
>
> Modified: clang-tools-extra/trunk/clangd/CodeComplete.h
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/CodeComplete.h?rev=343576&r1=343575&r2=343576&view=diff
> ==============================================================================
> --- clang-tools-extra/trunk/clangd/CodeComplete.h (original)
> +++ clang-tools-extra/trunk/clangd/CodeComplete.h Tue Oct 2 03:43:55 2018
> @@ -16,6 +16,7 @@
> #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_CODECOMPLETE_H
> #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_CODECOMPLETE_H
>
> +#include "ClangdUnit.h"
> #include "Headers.h"
> #include "Logger.h"
> #include "Path.h"
> @@ -221,8 +222,7 @@ struct SpeculativeFuzzyFind {
> /// destroyed when the async request finishes.
> CodeCompleteResult codeComplete(PathRef FileName,
> const tooling::CompileCommand &Command,
> - PrecompiledPreamble const *Preamble,
> - const IncludeStructure &PreambleInclusions,
> + const PreambleData *Preamble,
> StringRef Contents, Position Pos,
> IntrusiveRefCntPtr<vfs::FileSystem> VFS,
> std::shared_ptr<PCHContainerOperations> PCHs,
> @@ -232,8 +232,8 @@ CodeCompleteResult codeComplete(PathRef
> /// Get signature help at a specified \p Pos in \p FileName.
> SignatureHelp signatureHelp(PathRef FileName,
> const tooling::CompileCommand &Command,
> - PrecompiledPreamble const *Preamble,
> - StringRef Contents, Position Pos,
> + const PreambleData *Preamble, StringRef Contents,
> + Position Pos,
> IntrusiveRefCntPtr<vfs::FileSystem> VFS,
> std::shared_ptr<PCHContainerOperations> PCHs,
> const SymbolIndex *Index);
>
> Added: clang-tools-extra/trunk/clangd/FS.cpp
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/FS.cpp?rev=343576&view=auto
> ==============================================================================
> --- clang-tools-extra/trunk/clangd/FS.cpp (added)
> +++ clang-tools-extra/trunk/clangd/FS.cpp Tue Oct 2 03:43:55 2018
> @@ -0,0 +1,92 @@
> +//===--- FS.cpp - File system related utils ----------------------*- 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 "clang/Basic/VirtualFileSystem.h"
> +#include "llvm/ADT/None.h"
> +
> +namespace clang {
> +namespace clangd {
> +
> +void PreambleFileStatusCache::update(const vfs::FileSystem &FS, vfs::Status S) {
> + SmallString<32> PathStore(S.getName());
> + if (auto Err = FS.makeAbsolute(PathStore))
> + return;
> + // Stores the latest status in cache as it can change in a preamble build.
> + StatCache.insert({PathStore, std::move(S)});
> +}
> +
> +llvm::Optional<vfs::Status>
> +PreambleFileStatusCache::lookup(llvm::StringRef File) const {
> + auto I = StatCache.find(File);
> + if (I != StatCache.end())
> + return I->getValue();
> + return llvm::None;
> +}
> +
> +IntrusiveRefCntPtr<vfs::FileSystem> PreambleFileStatusCache::getProducingFS(
> + IntrusiveRefCntPtr<vfs::FileSystem> FS) {
> + // This invalidates old status in cache if files are re-`open()`ed or
> + // re-`stat()`ed in case file status has changed during preamble build.
> + class CollectFS : public vfs::ProxyFileSystem {
> + public:
> + CollectFS(IntrusiveRefCntPtr<vfs::FileSystem> FS,
> + PreambleFileStatusCache &StatCache)
> + : ProxyFileSystem(std::move(FS)), StatCache(StatCache) {}
> +
> + llvm::ErrorOr<std::unique_ptr<vfs::File>>
> + openFileForRead(const Twine &Path) override {
> + auto File = getUnderlyingFS().openFileForRead(Path);
> + if (!File || !*File)
> + return File;
> + // Eagerly stat opened file, as the followup `status` call on the file
> + // doesn't necessarily go through this FS. This puts some extra work on
> + // preamble build, but it should be worth it as preamble can be reused
> + // many times (e.g. code completion) and the repeated status call is
> + // likely to be cached in the underlying file system anyway.
> + if (auto S = File->get()->status())
> + StatCache.update(getUnderlyingFS(), std::move(*S));
> + return File;
> + }
> +
> + llvm::ErrorOr<vfs::Status> status(const Twine &Path) override {
> + auto S = getUnderlyingFS().status(Path);
> + if (S)
> + StatCache.update(getUnderlyingFS(), *S);
> + return S;
> + }
> +
> + private:
> + PreambleFileStatusCache &StatCache;
> + };
> + return IntrusiveRefCntPtr<CollectFS>(new CollectFS(std::move(FS), *this));
> +}
> +
> +IntrusiveRefCntPtr<vfs::FileSystem> PreambleFileStatusCache::getConsumingFS(
> + IntrusiveRefCntPtr<vfs::FileSystem> FS) const {
> + class CacheVFS : public vfs::ProxyFileSystem {
> + public:
> + CacheVFS(IntrusiveRefCntPtr<vfs::FileSystem> FS,
> + const PreambleFileStatusCache &StatCache)
> + : ProxyFileSystem(std::move(FS)), StatCache(StatCache) {}
> +
> + llvm::ErrorOr<vfs::Status> status(const Twine &Path) override {
> + if (auto S = StatCache.lookup(Path.str()))
> + return *S;
> + return getUnderlyingFS().status(Path);
> + }
> +
> + private:
> + const PreambleFileStatusCache &StatCache;
> + };
> + return IntrusiveRefCntPtr<CacheVFS>(new CacheVFS(std::move(FS), *this));
> +}
> +
> +} // namespace clangd
> +} // namespace clang
>
> Added: clang-tools-extra/trunk/clangd/FS.h
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/FS.h?rev=343576&view=auto
> ==============================================================================
> --- clang-tools-extra/trunk/clangd/FS.h (added)
> +++ clang-tools-extra/trunk/clangd/FS.h Tue Oct 2 03:43:55 2018
> @@ -0,0 +1,65 @@
> +//===--- FS.h - File system related utils ------------------------*- C++-*-===//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_FS_H
> +#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_FS_H
> +
> +#include "clang/Basic/VirtualFileSystem.h"
> +#include "llvm/ADT/Optional.h"
> +
> +namespace clang {
> +namespace clangd {
> +
> +/// Records status information for files open()ed or stat()ed during preamble
> +/// build, so we can avoid stat()s on the underlying FS when reusing the
> +/// preamble. For example, code completion can re-stat files when getting FileID
> +/// for source locations stored in preamble (e.g. checking whether a location is
> +/// in the main file).
> +///
> +/// The cache is keyed by absolute path of file name in cached status, as this
> +/// is what preamble stores.
> +///
> +/// The cache is not thread-safe when updates happen, so the use pattern should
> +/// be:
> +/// - One FS writes to the cache from one thread (or several but strictly
> +/// sequenced), e.g. when building preamble.
> +/// - Sequence point (no writes after this point, no reads before).
> +/// - Several FSs can read from the cache, e.g. code completions.
> +///
> +/// Note that the cache is only valid when reusing preamble.
> +class PreambleFileStatusCache {
> +public:
> + void update(const vfs::FileSystem &FS, vfs::Status S);
> + /// \p Path is a path stored in preamble.
> + llvm::Optional<vfs::Status> lookup(llvm::StringRef Path) const;
> +
> + /// Returns a VFS that collects file status.
> + /// Only cache stats for files that exist because
> + /// 1) we only care about existing files when reusing preamble, unlike
> + /// building preamble.
> + /// 2) we use the file name in the Status as the cache key.
> + ///
> + /// Note that the returned VFS should not outlive the cache.
> + IntrusiveRefCntPtr<vfs::FileSystem>
> + getProducingFS(IntrusiveRefCntPtr<vfs::FileSystem> FS);
> +
> + /// Returns a VFS that uses the cache collected.
> + ///
> + /// Note that the returned VFS should not outlive the cache.
> + IntrusiveRefCntPtr<vfs::FileSystem>
> + getConsumingFS(IntrusiveRefCntPtr<vfs::FileSystem> FS) const;
> +
> +private:
> + llvm::StringMap<vfs::Status> StatCache;
> +};
> +
> +} // namespace clangd
> +} // namespace clang
> +
> +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_FS_H
>
> Modified: clang-tools-extra/trunk/unittests/clangd/CMakeLists.txt
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clangd/CMakeLists.txt?rev=343576&r1=343575&r2=343576&view=diff
> ==============================================================================
> --- clang-tools-extra/trunk/unittests/clangd/CMakeLists.txt (original)
> +++ clang-tools-extra/trunk/unittests/clangd/CMakeLists.txt Tue Oct 2 03:43:55 2018
> @@ -21,6 +21,7 @@ add_extra_unittest(ClangdTests
> FileDistanceTests.cpp
> FileIndexTests.cpp
> FindSymbolsTests.cpp
> + FSTests.cpp
> FuzzyMatchTests.cpp
> GlobalCompilationDatabaseTests.cpp
> HeadersTests.cpp
>
> Modified: clang-tools-extra/trunk/unittests/clangd/ClangdTests.cpp
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clangd/ClangdTests.cpp?rev=343576&r1=343575&r2=343576&view=diff
> ==============================================================================
> --- clang-tools-extra/trunk/unittests/clangd/ClangdTests.cpp (original)
> +++ clang-tools-extra/trunk/unittests/clangd/ClangdTests.cpp Tue Oct 2 03:43:55 2018
> @@ -963,6 +963,71 @@ TEST_F(ClangdVFSTest, ChangedHeaderFromI
> 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
>
> Added: clang-tools-extra/trunk/unittests/clangd/FSTests.cpp
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clangd/FSTests.cpp?rev=343576&view=auto
> ==============================================================================
> --- clang-tools-extra/trunk/unittests/clangd/FSTests.cpp (added)
> +++ clang-tools-extra/trunk/unittests/clangd/FSTests.cpp Tue Oct 2 03:43:55 2018
> @@ -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
>
> Modified: clang-tools-extra/trunk/unittests/clangd/TestFS.cpp
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clangd/TestFS.cpp?rev=343576&r1=343575&r2=343576&view=diff
> ==============================================================================
> --- clang-tools-extra/trunk/unittests/clangd/TestFS.cpp (original)
> +++ clang-tools-extra/trunk/unittests/clangd/TestFS.cpp Tue Oct 2 03:43:55 2018
> @@ -23,6 +23,7 @@ buildTestFS(llvm::StringMap<std::string>
> 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(
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>
More information about the cfe-commits
mailing list