BackgroundRebuild.cpp
4.19 KB
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 "Logger.h"
#include "ParsedAST.h"
#include "Path.h"
#include "SourceCode.h"
#include "Symbol.h"
#include "Threading.h"
#include "Trace.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 "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