1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
|
//===-- BackgroundRebuild.cpp - when to rebuild thei background index -----===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "index/BackgroundRebuild.h"
#include "Compiler.h"
#include "Headers.h"
#include "ParsedAST.h"
#include "SourceCode.h"
#include "Symbol.h"
#include "URI.h"
#include "index/FileIndex.h"
#include "index/IndexAction.h"
#include "index/MemIndex.h"
#include "index/Ref.h"
#include "index/Relation.h"
#include "index/Serialization.h"
#include "index/SymbolCollector.h"
#include "support/Logger.h"
#include "support/Path.h"
#include "support/Threading.h"
#include "support/Trace.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/Threading.h"
#include <atomic>
#include <chrono>
#include <condition_variable>
#include <memory>
#include <mutex>
#include <numeric>
#include <queue>
#include <random>
#include <string>
#include <thread>
namespace clang {
namespace clangd {
bool BackgroundIndexRebuilder::enoughTUsToRebuild() const {
if (!ActiveVersion) // never built
return IndexedTUs == TUsBeforeFirstBuild; // use low threshold
// rebuild if we've reached the (higher) threshold
return IndexedTUs >= IndexedTUsAtLastRebuild + TUsBeforeRebuild;
}
void BackgroundIndexRebuilder::indexedTU() {
maybeRebuild("after indexing enough files", [this] {
++IndexedTUs;
if (Loading)
return false; // rebuild once loading finishes
if (ActiveVersion != StartedVersion) // currently building
return false; // no urgency, avoid overlapping builds
return enoughTUsToRebuild();
});
}
void BackgroundIndexRebuilder::idle() {
maybeRebuild("when background indexer is idle", [this] {
// rebuild if there's anything new in the index.
// (even if currently rebuilding! this ensures eventual completeness)
return IndexedTUs > IndexedTUsAtLastRebuild;
});
}
void BackgroundIndexRebuilder::startLoading() {
std::lock_guard<std::mutex> Lock(Mu);
if (!Loading)
LoadedShards = 0;
++Loading;
}
void BackgroundIndexRebuilder::loadedShard(size_t ShardCount) {
std::lock_guard<std::mutex> Lock(Mu);
assert(Loading);
LoadedShards += ShardCount;
}
void BackgroundIndexRebuilder::doneLoading() {
maybeRebuild("after loading index from disk", [this] {
assert(Loading);
--Loading;
if (Loading) // was loading multiple batches concurrently
return false; // rebuild once the last batch is done.
// Rebuild if we loaded any shards, or if we stopped an indexedTU rebuild.
return LoadedShards > 0 || enoughTUsToRebuild();
});
}
void BackgroundIndexRebuilder::shutdown() {
std::lock_guard<std::mutex> Lock(Mu);
ShouldStop = true;
}
void BackgroundIndexRebuilder::maybeRebuild(const char *Reason,
std::function<bool()> Check) {
unsigned BuildVersion = 0;
{
std::lock_guard<std::mutex> Lock(Mu);
if (!ShouldStop && Check()) {
BuildVersion = ++StartedVersion;
IndexedTUsAtLastRebuild = IndexedTUs;
}
}
if (BuildVersion) {
std::unique_ptr<SymbolIndex> NewIndex;
{
vlog("BackgroundIndex: building version {0} {1}", BuildVersion, Reason);
trace::Span Tracer("RebuildBackgroundIndex");
SPAN_ATTACH(Tracer, "reason", Reason);
NewIndex = Source->buildIndex(IndexType::Heavy, DuplicateHandling::Merge);
}
{
std::lock_guard<std::mutex> Lock(Mu);
// Guard against rebuild finishing in the wrong order.
if (BuildVersion > ActiveVersion) {
ActiveVersion = BuildVersion;
vlog("BackgroundIndex: serving version {0} ({1} bytes)", BuildVersion,
NewIndex->estimateMemoryUsage());
Target->reset(std::move(NewIndex));
}
}
}
}
} // namespace clangd
} // namespace clang
|