[clangd] Rewrite of logic to rebuild the background index serving structures.
Summary:
Previously it was rebuilding every 5s by default, which was much too frequent
in the long run - the goal was to provide an early build. There were also some
bugs. There were also some bugs, and a dedicated thread was used in production
but not tested.
- rebuilds are triggered by #TUs built, rather than time. This should scale
more sensibly to fast vs slow machines.
- there are two separate indexed-TU thresholds to trigger index build: 5 TUs
for the first build, 100 for subsequent rebuilds.
- rebuild is always done on the regular indexing threads, and is affected by
blockUntilIdle. This means unit/lit tests run the production configuration.
- fixed a bug where we'd rebuild after attempting to load shards, even if there
were no shards.
- the BackgroundIndexTests don't really test the subtleties of the rebuild
policy (for determinism, we call blockUntilIdle, so rebuild-on-idle is enough
to pass the tests). Instead, we expose the rebuilder as a separate class and
have fine-grained tests for it.
Reviewers: kadircet
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, jfb, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D64291
llvm-svn: 365531
2019-07-10 02:30:49 +08:00
|
|
|
//===-- 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"
|
2019-09-04 17:46:06 +08:00
|
|
|
#include "ParsedAST.h"
|
[clangd] Rewrite of logic to rebuild the background index serving structures.
Summary:
Previously it was rebuilding every 5s by default, which was much too frequent
in the long run - the goal was to provide an early build. There were also some
bugs. There were also some bugs, and a dedicated thread was used in production
but not tested.
- rebuilds are triggered by #TUs built, rather than time. This should scale
more sensibly to fast vs slow machines.
- there are two separate indexed-TU thresholds to trigger index build: 5 TUs
for the first build, 100 for subsequent rebuilds.
- rebuild is always done on the regular indexing threads, and is affected by
blockUntilIdle. This means unit/lit tests run the production configuration.
- fixed a bug where we'd rebuild after attempting to load shards, even if there
were no shards.
- the BackgroundIndexTests don't really test the subtleties of the rebuild
policy (for determinism, we call blockUntilIdle, so rebuild-on-idle is enough
to pass the tests). Instead, we expose the rebuilder as a separate class and
have fine-grained tests for it.
Reviewers: kadircet
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, jfb, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D64291
llvm-svn: 365531
2019-07-10 02:30:49 +08:00
|
|
|
#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"
|
[clangd] Move non-clang base pieces into separate support/ lib. NFCI
Summary:
This enforces layering, reduces a sprawling clangd/ directory, and makes life
easier for embedders.
Reviewers: kbobyrev
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D79014
2020-04-28 23:49:17 +08:00
|
|
|
#include "support/Logger.h"
|
|
|
|
#include "support/Path.h"
|
|
|
|
#include "support/Threading.h"
|
|
|
|
#include "support/Trace.h"
|
[clangd] Rewrite of logic to rebuild the background index serving structures.
Summary:
Previously it was rebuilding every 5s by default, which was much too frequent
in the long run - the goal was to provide an early build. There were also some
bugs. There were also some bugs, and a dedicated thread was used in production
but not tested.
- rebuilds are triggered by #TUs built, rather than time. This should scale
more sensibly to fast vs slow machines.
- there are two separate indexed-TU thresholds to trigger index build: 5 TUs
for the first build, 100 for subsequent rebuilds.
- rebuild is always done on the regular indexing threads, and is affected by
blockUntilIdle. This means unit/lit tests run the production configuration.
- fixed a bug where we'd rebuild after attempting to load shards, even if there
were no shards.
- the BackgroundIndexTests don't really test the subtleties of the rebuild
policy (for determinism, we call blockUntilIdle, so rebuild-on-idle is enough
to pass the tests). Instead, we expose the rebuilder as a separate class and
have fine-grained tests for it.
Reviewers: kadircet
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, jfb, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D64291
llvm-svn: 365531
2019-07-10 02:30:49 +08:00
|
|
|
#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)
|
2019-07-19 18:18:52 +08:00
|
|
|
LoadedShards = 0;
|
[clangd] Rewrite of logic to rebuild the background index serving structures.
Summary:
Previously it was rebuilding every 5s by default, which was much too frequent
in the long run - the goal was to provide an early build. There were also some
bugs. There were also some bugs, and a dedicated thread was used in production
but not tested.
- rebuilds are triggered by #TUs built, rather than time. This should scale
more sensibly to fast vs slow machines.
- there are two separate indexed-TU thresholds to trigger index build: 5 TUs
for the first build, 100 for subsequent rebuilds.
- rebuild is always done on the regular indexing threads, and is affected by
blockUntilIdle. This means unit/lit tests run the production configuration.
- fixed a bug where we'd rebuild after attempting to load shards, even if there
were no shards.
- the BackgroundIndexTests don't really test the subtleties of the rebuild
policy (for determinism, we call blockUntilIdle, so rebuild-on-idle is enough
to pass the tests). Instead, we expose the rebuilder as a separate class and
have fine-grained tests for it.
Reviewers: kadircet
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, jfb, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D64291
llvm-svn: 365531
2019-07-10 02:30:49 +08:00
|
|
|
++Loading;
|
|
|
|
}
|
2019-07-19 18:18:52 +08:00
|
|
|
void BackgroundIndexRebuilder::loadedShard(size_t ShardCount) {
|
[clangd] Rewrite of logic to rebuild the background index serving structures.
Summary:
Previously it was rebuilding every 5s by default, which was much too frequent
in the long run - the goal was to provide an early build. There were also some
bugs. There were also some bugs, and a dedicated thread was used in production
but not tested.
- rebuilds are triggered by #TUs built, rather than time. This should scale
more sensibly to fast vs slow machines.
- there are two separate indexed-TU thresholds to trigger index build: 5 TUs
for the first build, 100 for subsequent rebuilds.
- rebuild is always done on the regular indexing threads, and is affected by
blockUntilIdle. This means unit/lit tests run the production configuration.
- fixed a bug where we'd rebuild after attempting to load shards, even if there
were no shards.
- the BackgroundIndexTests don't really test the subtleties of the rebuild
policy (for determinism, we call blockUntilIdle, so rebuild-on-idle is enough
to pass the tests). Instead, we expose the rebuilder as a separate class and
have fine-grained tests for it.
Reviewers: kadircet
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, jfb, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D64291
llvm-svn: 365531
2019-07-10 02:30:49 +08:00
|
|
|
std::lock_guard<std::mutex> Lock(Mu);
|
|
|
|
assert(Loading);
|
2019-07-19 18:18:52 +08:00
|
|
|
LoadedShards += ShardCount;
|
[clangd] Rewrite of logic to rebuild the background index serving structures.
Summary:
Previously it was rebuilding every 5s by default, which was much too frequent
in the long run - the goal was to provide an early build. There were also some
bugs. There were also some bugs, and a dedicated thread was used in production
but not tested.
- rebuilds are triggered by #TUs built, rather than time. This should scale
more sensibly to fast vs slow machines.
- there are two separate indexed-TU thresholds to trigger index build: 5 TUs
for the first build, 100 for subsequent rebuilds.
- rebuild is always done on the regular indexing threads, and is affected by
blockUntilIdle. This means unit/lit tests run the production configuration.
- fixed a bug where we'd rebuild after attempting to load shards, even if there
were no shards.
- the BackgroundIndexTests don't really test the subtleties of the rebuild
policy (for determinism, we call blockUntilIdle, so rebuild-on-idle is enough
to pass the tests). Instead, we expose the rebuilder as a separate class and
have fine-grained tests for it.
Reviewers: kadircet
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, jfb, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D64291
llvm-svn: 365531
2019-07-10 02:30:49 +08:00
|
|
|
}
|
|
|
|
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.
|
2019-07-19 18:18:52 +08:00
|
|
|
return LoadedShards > 0 || enoughTUsToRebuild();
|
[clangd] Rewrite of logic to rebuild the background index serving structures.
Summary:
Previously it was rebuilding every 5s by default, which was much too frequent
in the long run - the goal was to provide an early build. There were also some
bugs. There were also some bugs, and a dedicated thread was used in production
but not tested.
- rebuilds are triggered by #TUs built, rather than time. This should scale
more sensibly to fast vs slow machines.
- there are two separate indexed-TU thresholds to trigger index build: 5 TUs
for the first build, 100 for subsequent rebuilds.
- rebuild is always done on the regular indexing threads, and is affected by
blockUntilIdle. This means unit/lit tests run the production configuration.
- fixed a bug where we'd rebuild after attempting to load shards, even if there
were no shards.
- the BackgroundIndexTests don't really test the subtleties of the rebuild
policy (for determinism, we call blockUntilIdle, so rebuild-on-idle is enough
to pass the tests). Instead, we expose the rebuilder as a separate class and
have fine-grained tests for it.
Reviewers: kadircet
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, jfb, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D64291
llvm-svn: 365531
2019-07-10 02:30:49 +08:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
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
|