[clangd] Minimal implementation of automatic static index (not enabled).
Summary:
See tinyurl.com/clangd-automatic-index for design and goals.
Lots of limitations to keep this patch smallish, TODOs everywhere:
- no serialization to disk
- no changes to dynamic index, which now has a much simpler job
- no partitioning of symbols by file to avoid duplication of header symbols
- no reindexing of edited files
- only a single worker thread
- compilation database is slurped synchronously (doesn't scale)
- uses memindex, rebuilds after every file (should be dex, periodically)
It's not hooked up to ClangdServer/ClangdLSPServer yet: the layering
isn't clear (it should really be in ClangdServer, but ClangdLSPServer
has all the CDB interactions).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, jfb, cfe-commits
Differential Revision: https://reviews.llvm.org/D53032
llvm-svn: 344513
2018-10-15 21:34:10 +08:00
|
|
|
//===-- Background.cpp - Build an index in a background thread ------------===//
|
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// 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
|
[clangd] Minimal implementation of automatic static index (not enabled).
Summary:
See tinyurl.com/clangd-automatic-index for design and goals.
Lots of limitations to keep this patch smallish, TODOs everywhere:
- no serialization to disk
- no changes to dynamic index, which now has a much simpler job
- no partitioning of symbols by file to avoid duplication of header symbols
- no reindexing of edited files
- only a single worker thread
- compilation database is slurped synchronously (doesn't scale)
- uses memindex, rebuilds after every file (should be dex, periodically)
It's not hooked up to ClangdServer/ClangdLSPServer yet: the layering
isn't clear (it should really be in ClangdServer, but ClangdLSPServer
has all the CDB interactions).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, jfb, cfe-commits
Differential Revision: https://reviews.llvm.org/D53032
llvm-svn: 344513
2018-10-15 21:34:10 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "index/Background.h"
|
|
|
|
#include "Compiler.h"
|
2019-07-04 17:51:43 +08:00
|
|
|
#include "Headers.h"
|
2019-09-04 17:46:06 +08:00
|
|
|
#include "ParsedAST.h"
|
2018-11-28 00:08:53 +08:00
|
|
|
#include "SourceCode.h"
|
2019-02-28 21:23:03 +08:00
|
|
|
#include "Symbol.h"
|
2018-11-06 18:55:21 +08:00
|
|
|
#include "URI.h"
|
2019-07-19 18:18:52 +08:00
|
|
|
#include "index/BackgroundIndexLoader.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 "index/FileIndex.h"
|
[clangd] Minimal implementation of automatic static index (not enabled).
Summary:
See tinyurl.com/clangd-automatic-index for design and goals.
Lots of limitations to keep this patch smallish, TODOs everywhere:
- no serialization to disk
- no changes to dynamic index, which now has a much simpler job
- no partitioning of symbols by file to avoid duplication of header symbols
- no reindexing of edited files
- only a single worker thread
- compilation database is slurped synchronously (doesn't scale)
- uses memindex, rebuilds after every file (should be dex, periodically)
It's not hooked up to ClangdServer/ClangdLSPServer yet: the layering
isn't clear (it should really be in ClangdServer, but ClangdLSPServer
has all the CDB interactions).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, jfb, cfe-commits
Differential Revision: https://reviews.llvm.org/D53032
llvm-svn: 344513
2018-10-15 21:34:10 +08:00
|
|
|
#include "index/IndexAction.h"
|
|
|
|
#include "index/MemIndex.h"
|
2019-07-04 17:51:43 +08:00
|
|
|
#include "index/Ref.h"
|
|
|
|
#include "index/Relation.h"
|
[clangd] Minimal implementation of automatic static index (not enabled).
Summary:
See tinyurl.com/clangd-automatic-index for design and goals.
Lots of limitations to keep this patch smallish, TODOs everywhere:
- no serialization to disk
- no changes to dynamic index, which now has a much simpler job
- no partitioning of symbols by file to avoid duplication of header symbols
- no reindexing of edited files
- only a single worker thread
- compilation database is slurped synchronously (doesn't scale)
- uses memindex, rebuilds after every file (should be dex, periodically)
It's not hooked up to ClangdServer/ClangdLSPServer yet: the layering
isn't clear (it should really be in ClangdServer, but ClangdLSPServer
has all the CDB interactions).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, jfb, cfe-commits
Differential Revision: https://reviews.llvm.org/D53032
llvm-svn: 344513
2018-10-15 21:34:10 +08:00
|
|
|
#include "index/Serialization.h"
|
2018-11-06 18:55:21 +08:00
|
|
|
#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/Context.h"
|
|
|
|
#include "support/FSProvider.h"
|
|
|
|
#include "support/Logger.h"
|
|
|
|
#include "support/Path.h"
|
|
|
|
#include "support/Threading.h"
|
|
|
|
#include "support/Trace.h"
|
2018-11-06 18:55:21 +08:00
|
|
|
#include "clang/Basic/SourceLocation.h"
|
|
|
|
#include "clang/Basic/SourceManager.h"
|
2019-07-12 18:18:42 +08:00
|
|
|
#include "clang/Driver/Types.h"
|
2019-07-19 18:18:52 +08:00
|
|
|
#include "llvm/ADT/ArrayRef.h"
|
|
|
|
#include "llvm/ADT/DenseSet.h"
|
2019-07-04 17:51:53 +08:00
|
|
|
#include "llvm/ADT/Hashing.h"
|
2018-11-06 18:55:21 +08:00
|
|
|
#include "llvm/ADT/STLExtras.h"
|
2018-12-17 20:30:27 +08:00
|
|
|
#include "llvm/ADT/ScopeExit.h"
|
2018-11-06 18:55:21 +08:00
|
|
|
#include "llvm/ADT/StringMap.h"
|
|
|
|
#include "llvm/ADT/StringRef.h"
|
2019-07-04 17:51:43 +08:00
|
|
|
#include "llvm/ADT/StringSet.h"
|
|
|
|
#include "llvm/Support/Error.h"
|
2019-07-11 21:34:38 +08:00
|
|
|
#include "llvm/Support/Path.h"
|
2019-04-18 21:46:40 +08:00
|
|
|
#include "llvm/Support/Threading.h"
|
2018-11-16 17:03:56 +08:00
|
|
|
|
2019-07-11 21:34:38 +08:00
|
|
|
#include <algorithm>
|
2019-04-18 21:46:40 +08:00
|
|
|
#include <atomic>
|
2018-12-18 23:39:33 +08:00
|
|
|
#include <chrono>
|
[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 <condition_variable>
|
2019-07-19 18:18:52 +08:00
|
|
|
#include <cstddef>
|
2018-11-16 17:03:56 +08:00
|
|
|
#include <memory>
|
[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 <mutex>
|
2018-11-26 21:35:02 +08:00
|
|
|
#include <numeric>
|
2018-11-16 17:03:56 +08:00
|
|
|
#include <queue>
|
[clangd] Minimal implementation of automatic static index (not enabled).
Summary:
See tinyurl.com/clangd-automatic-index for design and goals.
Lots of limitations to keep this patch smallish, TODOs everywhere:
- no serialization to disk
- no changes to dynamic index, which now has a much simpler job
- no partitioning of symbols by file to avoid duplication of header symbols
- no reindexing of edited files
- only a single worker thread
- compilation database is slurped synchronously (doesn't scale)
- uses memindex, rebuilds after every file (should be dex, periodically)
It's not hooked up to ClangdServer/ClangdLSPServer yet: the layering
isn't clear (it should really be in ClangdServer, but ClangdLSPServer
has all the CDB interactions).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, jfb, cfe-commits
Differential Revision: https://reviews.llvm.org/D53032
llvm-svn: 344513
2018-10-15 21:34:10 +08:00
|
|
|
#include <random>
|
2018-11-06 18:55:21 +08:00
|
|
|
#include <string>
|
2018-12-18 23:39:33 +08:00
|
|
|
#include <thread>
|
2019-07-19 18:18:52 +08:00
|
|
|
#include <utility>
|
|
|
|
#include <vector>
|
[clangd] Minimal implementation of automatic static index (not enabled).
Summary:
See tinyurl.com/clangd-automatic-index for design and goals.
Lots of limitations to keep this patch smallish, TODOs everywhere:
- no serialization to disk
- no changes to dynamic index, which now has a much simpler job
- no partitioning of symbols by file to avoid duplication of header symbols
- no reindexing of edited files
- only a single worker thread
- compilation database is slurped synchronously (doesn't scale)
- uses memindex, rebuilds after every file (should be dex, periodically)
It's not hooked up to ClangdServer/ClangdLSPServer yet: the layering
isn't clear (it should really be in ClangdServer, but ClangdLSPServer
has all the CDB interactions).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, jfb, cfe-commits
Differential Revision: https://reviews.llvm.org/D53032
llvm-svn: 344513
2018-10-15 21:34:10 +08:00
|
|
|
|
|
|
|
namespace clang {
|
|
|
|
namespace clangd {
|
2018-12-04 19:31:57 +08:00
|
|
|
namespace {
|
2019-04-18 21:46:40 +08:00
|
|
|
|
2019-01-11 01:03:04 +08:00
|
|
|
// We cannot use vfs->makeAbsolute because Cmd.FileName is either absolute or
|
|
|
|
// relative to Cmd.Directory, which might not be the same as current working
|
|
|
|
// directory.
|
|
|
|
llvm::SmallString<128> getAbsolutePath(const tooling::CompileCommand &Cmd) {
|
|
|
|
llvm::SmallString<128> AbsolutePath;
|
|
|
|
if (llvm::sys::path::is_absolute(Cmd.Filename)) {
|
|
|
|
AbsolutePath = Cmd.Filename;
|
|
|
|
} else {
|
|
|
|
AbsolutePath = Cmd.Directory;
|
|
|
|
llvm::sys::path::append(AbsolutePath, Cmd.Filename);
|
2019-03-08 17:57:33 +08:00
|
|
|
llvm::sys::path::remove_dots(AbsolutePath, true);
|
2019-01-11 01:03:04 +08:00
|
|
|
}
|
|
|
|
return AbsolutePath;
|
|
|
|
}
|
2019-07-19 18:18:52 +08:00
|
|
|
|
|
|
|
bool shardIsStale(const LoadedShard &LS, llvm::vfs::FileSystem *FS) {
|
|
|
|
auto Buf = FS->getBufferForFile(LS.AbsolutePath);
|
|
|
|
if (!Buf) {
|
|
|
|
elog("Background-index: Couldn't read {0} to validate stored index: {1}",
|
|
|
|
LS.AbsolutePath, Buf.getError().message());
|
|
|
|
// There is no point in indexing an unreadable file.
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return digest(Buf->get()->getBuffer()) != LS.Digest;
|
|
|
|
}
|
|
|
|
|
2018-12-04 19:31:57 +08:00
|
|
|
} // namespace
|
[clangd] Minimal implementation of automatic static index (not enabled).
Summary:
See tinyurl.com/clangd-automatic-index for design and goals.
Lots of limitations to keep this patch smallish, TODOs everywhere:
- no serialization to disk
- no changes to dynamic index, which now has a much simpler job
- no partitioning of symbols by file to avoid duplication of header symbols
- no reindexing of edited files
- only a single worker thread
- compilation database is slurped synchronously (doesn't scale)
- uses memindex, rebuilds after every file (should be dex, periodically)
It's not hooked up to ClangdServer/ClangdLSPServer yet: the layering
isn't clear (it should really be in ClangdServer, but ClangdLSPServer
has all the CDB interactions).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, jfb, cfe-commits
Differential Revision: https://reviews.llvm.org/D53032
llvm-svn: 344513
2018-10-15 21:34:10 +08:00
|
|
|
|
2018-11-16 17:03:56 +08:00
|
|
|
BackgroundIndex::BackgroundIndex(
|
2019-01-22 17:10:20 +08:00
|
|
|
Context BackgroundContext, const FileSystemProvider &FSProvider,
|
|
|
|
const GlobalCompilationDatabase &CDB,
|
[clangd] Show background index status using LSP 3.15 work-done progress notifications
Summary:
It simply shows the completed/total items on the background queue, e.g.
indexing: 233/1000
The denominator is reset to zero every time the queue goes idle.
The protocol is fairly complicated here (requires creating a remote "progress"
resource before sending updates). We implement the full protocol, but I've added
an extension allowing it to be skipped to reduce the burden on clients - in
particular the lit test takes this shortcut.
The addition of background index progress to DiagnosticConsumer seems ridiculous
at first glance, but I believe that interface is trending in the direction of
"ClangdServer callbacks" anyway. It's due for a rename, but otherwise actually
fits.
Reviewers: kadircet, usaxena95
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, jfb, cfe-commits, llvm-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D73218
2020-01-23 02:41:45 +08:00
|
|
|
BackgroundIndexStorage::Factory IndexStorageFactory, size_t ThreadPoolSize,
|
|
|
|
std::function<void(BackgroundQueue::Stats)> OnProgress)
|
|
|
|
: SwapIndex(std::make_unique<MemIndex>()), FSProvider(FSProvider), CDB(CDB),
|
|
|
|
BackgroundContext(std::move(BackgroundContext)),
|
2019-07-16 18:17:06 +08:00
|
|
|
Rebuilder(this, &IndexedSymbols, ThreadPoolSize),
|
[clangd] Auto-index watches global CDB for changes.
Summary:
Instead of receiving compilation commands, auto-index is triggered by just
filenames to reindex, and gets commands from the global comp DB internally.
This has advantages:
- more of the work can be done asynchronously (fetching compilation commands
upfront can be slow for large CDBs)
- we get access to the CDB which can be used to retrieve interpolated commands
for headers (useful in some cases where the original TU goes away)
- fits nicely with the filename-only change observation from r347297
The interface to GlobalCompilationDatabase gets extended: when retrieving a
compile command, the GCDB can optionally report the project the file belongs to.
This naturally fits together with getCompileCommand: it's hard to implement one
without the other. But because most callers don't care, I've ended up with an
awkward optional-out-param-in-virtual method pattern - maybe there's a better
one.
This is the main missing integration point between ClangdServer and
BackgroundIndex, after this we should be able to add an auto-index flag.
Reviewers: ioeric, kadircet
Subscribers: MaskRay, jkorous, arphaman, cfe-commits, ilya-biryukov
Differential Revision: https://reviews.llvm.org/D54865
llvm-svn: 347538
2018-11-26 17:51:50 +08:00
|
|
|
IndexStorageFactory(std::move(IndexStorageFactory)),
|
[clangd] Show background index status using LSP 3.15 work-done progress notifications
Summary:
It simply shows the completed/total items on the background queue, e.g.
indexing: 233/1000
The denominator is reset to zero every time the queue goes idle.
The protocol is fairly complicated here (requires creating a remote "progress"
resource before sending updates). We implement the full protocol, but I've added
an extension allowing it to be skipped to reduce the burden on clients - in
particular the lit test takes this shortcut.
The addition of background index progress to DiagnosticConsumer seems ridiculous
at first glance, but I believe that interface is trending in the direction of
"ClangdServer callbacks" anyway. It's due for a rename, but otherwise actually
fits.
Reviewers: kadircet, usaxena95
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, jfb, cfe-commits, llvm-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D73218
2020-01-23 02:41:45 +08:00
|
|
|
Queue(std::move(OnProgress)),
|
[clangd] Auto-index watches global CDB for changes.
Summary:
Instead of receiving compilation commands, auto-index is triggered by just
filenames to reindex, and gets commands from the global comp DB internally.
This has advantages:
- more of the work can be done asynchronously (fetching compilation commands
upfront can be slow for large CDBs)
- we get access to the CDB which can be used to retrieve interpolated commands
for headers (useful in some cases where the original TU goes away)
- fits nicely with the filename-only change observation from r347297
The interface to GlobalCompilationDatabase gets extended: when retrieving a
compile command, the GCDB can optionally report the project the file belongs to.
This naturally fits together with getCompileCommand: it's hard to implement one
without the other. But because most callers don't care, I've ended up with an
awkward optional-out-param-in-virtual method pattern - maybe there's a better
one.
This is the main missing integration point between ClangdServer and
BackgroundIndex, after this we should be able to add an auto-index flag.
Reviewers: ioeric, kadircet
Subscribers: MaskRay, jkorous, arphaman, cfe-commits, ilya-biryukov
Differential Revision: https://reviews.llvm.org/D54865
llvm-svn: 347538
2018-11-26 17:51:50 +08:00
|
|
|
CommandsChanged(
|
|
|
|
CDB.watch([&](const std::vector<std::string> &ChangedFiles) {
|
|
|
|
enqueue(ChangedFiles);
|
|
|
|
})) {
|
[Support] On Windows, ensure hardware_concurrency() extends to all CPU sockets and all NUMA groups
The goal of this patch is to maximize CPU utilization on multi-socket or high core count systems, so that parallel computations such as LLD/ThinLTO can use all hardware threads in the system. Before this patch, on Windows, a maximum of 64 hardware threads could be used at most, in some cases dispatched only on one CPU socket.
== Background ==
Windows doesn't have a flat cpu_set_t like Linux. Instead, it projects hardware CPUs (or NUMA nodes) to applications through a concept of "processor groups". A "processor" is the smallest unit of execution on a CPU, that is, an hyper-thread if SMT is active; a core otherwise. There's a limit of 32-bit processors on older 32-bit versions of Windows, which later was raised to 64-processors with 64-bit versions of Windows. This limit comes from the affinity mask, which historically is represented by the sizeof(void*). Consequently, the concept of "processor groups" was introduced for dealing with systems with more than 64 hyper-threads.
By default, the Windows OS assigns only one "processor group" to each starting application, in a round-robin manner. If the application wants to use more processors, it needs to programmatically enable it, by assigning threads to other "processor groups". This also means that affinity cannot cross "processor group" boundaries; one can only specify a "preferred" group on start-up, but the application is free to allocate more groups if it wants to.
This creates a peculiar situation, where newer CPUs like the AMD EPYC 7702P (64-cores, 128-hyperthreads) are projected by the OS as two (2) "processor groups". This means that by default, an application can only use half of the cores. This situation could only get worse in the years to come, as dies with more cores will appear on the market.
== The problem ==
The heavyweight_hardware_concurrency() API was introduced so that only *one hardware thread per core* was used. Once that API returns, that original intention is lost, only the number of threads is retained. Consider a situation, on Windows, where the system has 2 CPU sockets, 18 cores each, each core having 2 hyper-threads, for a total of 72 hyper-threads. Both heavyweight_hardware_concurrency() and hardware_concurrency() currently return 36, because on Windows they are simply wrappers over std::thread::hardware_concurrency() -- which can only return processors from the current "processor group".
== The changes in this patch ==
To solve this situation, we capture (and retain) the initial intention until the point of usage, through a new ThreadPoolStrategy class. The number of threads to use is deferred as late as possible, until the moment where the std::threads are created (ThreadPool in the case of ThinLTO).
When using hardware_concurrency(), setting ThreadCount to 0 now means to use all the possible hardware CPU (SMT) threads. Providing a ThreadCount above to the maximum number of threads will have no effect, the maximum will be used instead.
The heavyweight_hardware_concurrency() is similar to hardware_concurrency(), except that only one thread per hardware *core* will be used.
When LLVM_ENABLE_THREADS is OFF, the threading APIs will always return 1, to ensure any caller loops will be exercised at least once.
Differential Revision: https://reviews.llvm.org/D71775
2020-02-14 11:49:57 +08:00
|
|
|
assert(Rebuilder.TUsBeforeFirstBuild > 0 &&
|
|
|
|
"Thread pool size can't be zero.");
|
2018-11-16 17:41:14 +08:00
|
|
|
assert(this->IndexStorageFactory && "Storage factory can not be null!");
|
[Support] On Windows, ensure hardware_concurrency() extends to all CPU sockets and all NUMA groups
The goal of this patch is to maximize CPU utilization on multi-socket or high core count systems, so that parallel computations such as LLD/ThinLTO can use all hardware threads in the system. Before this patch, on Windows, a maximum of 64 hardware threads could be used at most, in some cases dispatched only on one CPU socket.
== Background ==
Windows doesn't have a flat cpu_set_t like Linux. Instead, it projects hardware CPUs (or NUMA nodes) to applications through a concept of "processor groups". A "processor" is the smallest unit of execution on a CPU, that is, an hyper-thread if SMT is active; a core otherwise. There's a limit of 32-bit processors on older 32-bit versions of Windows, which later was raised to 64-processors with 64-bit versions of Windows. This limit comes from the affinity mask, which historically is represented by the sizeof(void*). Consequently, the concept of "processor groups" was introduced for dealing with systems with more than 64 hyper-threads.
By default, the Windows OS assigns only one "processor group" to each starting application, in a round-robin manner. If the application wants to use more processors, it needs to programmatically enable it, by assigning threads to other "processor groups". This also means that affinity cannot cross "processor group" boundaries; one can only specify a "preferred" group on start-up, but the application is free to allocate more groups if it wants to.
This creates a peculiar situation, where newer CPUs like the AMD EPYC 7702P (64-cores, 128-hyperthreads) are projected by the OS as two (2) "processor groups". This means that by default, an application can only use half of the cores. This situation could only get worse in the years to come, as dies with more cores will appear on the market.
== The problem ==
The heavyweight_hardware_concurrency() API was introduced so that only *one hardware thread per core* was used. Once that API returns, that original intention is lost, only the number of threads is retained. Consider a situation, on Windows, where the system has 2 CPU sockets, 18 cores each, each core having 2 hyper-threads, for a total of 72 hyper-threads. Both heavyweight_hardware_concurrency() and hardware_concurrency() currently return 36, because on Windows they are simply wrappers over std::thread::hardware_concurrency() -- which can only return processors from the current "processor group".
== The changes in this patch ==
To solve this situation, we capture (and retain) the initial intention until the point of usage, through a new ThreadPoolStrategy class. The number of threads to use is deferred as late as possible, until the moment where the std::threads are created (ThreadPool in the case of ThinLTO).
When using hardware_concurrency(), setting ThreadCount to 0 now means to use all the possible hardware CPU (SMT) threads. Providing a ThreadCount above to the maximum number of threads will have no effect, the maximum will be used instead.
The heavyweight_hardware_concurrency() is similar to hardware_concurrency(), except that only one thread per hardware *core* will be used.
When LLVM_ENABLE_THREADS is OFF, the threading APIs will always return 1, to ensure any caller loops will be exercised at least once.
Differential Revision: https://reviews.llvm.org/D71775
2020-02-14 11:49:57 +08:00
|
|
|
for (unsigned I = 0; I < Rebuilder.TUsBeforeFirstBuild; ++I) {
|
2019-07-11 21:34:38 +08:00
|
|
|
ThreadPool.runAsync("background-worker-" + llvm::Twine(I + 1), [this] {
|
|
|
|
WithContext Ctx(this->BackgroundContext.clone());
|
|
|
|
Queue.work([&] { Rebuilder.idle(); });
|
|
|
|
});
|
2019-05-09 20:04:07 +08:00
|
|
|
}
|
2018-10-30 20:13:27 +08:00
|
|
|
}
|
[clangd] Minimal implementation of automatic static index (not enabled).
Summary:
See tinyurl.com/clangd-automatic-index for design and goals.
Lots of limitations to keep this patch smallish, TODOs everywhere:
- no serialization to disk
- no changes to dynamic index, which now has a much simpler job
- no partitioning of symbols by file to avoid duplication of header symbols
- no reindexing of edited files
- only a single worker thread
- compilation database is slurped synchronously (doesn't scale)
- uses memindex, rebuilds after every file (should be dex, periodically)
It's not hooked up to ClangdServer/ClangdLSPServer yet: the layering
isn't clear (it should really be in ClangdServer, but ClangdLSPServer
has all the CDB interactions).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, jfb, cfe-commits
Differential Revision: https://reviews.llvm.org/D53032
llvm-svn: 344513
2018-10-15 21:34:10 +08:00
|
|
|
|
|
|
|
BackgroundIndex::~BackgroundIndex() {
|
|
|
|
stop();
|
2019-05-09 20:04:07 +08:00
|
|
|
ThreadPool.wait();
|
[clangd] Minimal implementation of automatic static index (not enabled).
Summary:
See tinyurl.com/clangd-automatic-index for design and goals.
Lots of limitations to keep this patch smallish, TODOs everywhere:
- no serialization to disk
- no changes to dynamic index, which now has a much simpler job
- no partitioning of symbols by file to avoid duplication of header symbols
- no reindexing of edited files
- only a single worker thread
- compilation database is slurped synchronously (doesn't scale)
- uses memindex, rebuilds after every file (should be dex, periodically)
It's not hooked up to ClangdServer/ClangdLSPServer yet: the layering
isn't clear (it should really be in ClangdServer, but ClangdLSPServer
has all the CDB interactions).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, jfb, cfe-commits
Differential Revision: https://reviews.llvm.org/D53032
llvm-svn: 344513
2018-10-15 21:34:10 +08:00
|
|
|
}
|
|
|
|
|
2019-07-11 21:34:38 +08:00
|
|
|
BackgroundQueue::Task BackgroundIndex::changedFilesTask(
|
|
|
|
const std::vector<std::string> &ChangedFiles) {
|
|
|
|
BackgroundQueue::Task T([this, ChangedFiles] {
|
|
|
|
trace::Span Tracer("BackgroundIndexEnqueue");
|
|
|
|
// We're doing this asynchronously, because we'll read shards here too.
|
|
|
|
log("Enqueueing {0} commands for indexing", ChangedFiles.size());
|
|
|
|
SPAN_ATTACH(Tracer, "files", int64_t(ChangedFiles.size()));
|
|
|
|
|
2019-07-19 18:18:52 +08:00
|
|
|
auto NeedsReIndexing = loadProject(std::move(ChangedFiles));
|
2019-07-11 21:34:38 +08:00
|
|
|
// Run indexing for files that need to be updated.
|
|
|
|
std::shuffle(NeedsReIndexing.begin(), NeedsReIndexing.end(),
|
|
|
|
std::mt19937(std::random_device{}()));
|
|
|
|
std::vector<BackgroundQueue::Task> Tasks;
|
|
|
|
Tasks.reserve(NeedsReIndexing.size());
|
2019-07-19 18:18:52 +08:00
|
|
|
for (auto &Cmd : NeedsReIndexing)
|
|
|
|
Tasks.push_back(indexFileTask(std::move(Cmd)));
|
2019-07-11 21:34:38 +08:00
|
|
|
Queue.append(std::move(Tasks));
|
|
|
|
});
|
|
|
|
|
|
|
|
T.QueuePri = LoadShards;
|
|
|
|
T.ThreadPri = llvm::ThreadPriority::Default;
|
|
|
|
return T;
|
[clangd] Minimal implementation of automatic static index (not enabled).
Summary:
See tinyurl.com/clangd-automatic-index for design and goals.
Lots of limitations to keep this patch smallish, TODOs everywhere:
- no serialization to disk
- no changes to dynamic index, which now has a much simpler job
- no partitioning of symbols by file to avoid duplication of header symbols
- no reindexing of edited files
- only a single worker thread
- compilation database is slurped synchronously (doesn't scale)
- uses memindex, rebuilds after every file (should be dex, periodically)
It's not hooked up to ClangdServer/ClangdLSPServer yet: the layering
isn't clear (it should really be in ClangdServer, but ClangdLSPServer
has all the CDB interactions).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, jfb, cfe-commits
Differential Revision: https://reviews.llvm.org/D53032
llvm-svn: 344513
2018-10-15 21:34:10 +08:00
|
|
|
}
|
|
|
|
|
2019-07-12 18:18:42 +08:00
|
|
|
static llvm::StringRef filenameWithoutExtension(llvm::StringRef Path) {
|
|
|
|
Path = llvm::sys::path::filename(Path);
|
|
|
|
return Path.drop_back(llvm::sys::path::extension(Path).size());
|
|
|
|
}
|
|
|
|
|
2019-07-11 21:34:38 +08:00
|
|
|
BackgroundQueue::Task
|
2019-07-19 18:18:52 +08:00
|
|
|
BackgroundIndex::indexFileTask(tooling::CompileCommand Cmd) {
|
|
|
|
BackgroundQueue::Task T([this, Cmd] {
|
2019-07-11 21:34:38 +08:00
|
|
|
// We can't use llvm::StringRef here since we are going to
|
|
|
|
// move from Cmd during the call below.
|
|
|
|
const std::string FileName = Cmd.Filename;
|
2019-07-19 18:18:52 +08:00
|
|
|
if (auto Error = index(std::move(Cmd)))
|
2019-07-11 21:34:38 +08:00
|
|
|
elog("Indexing {0} failed: {1}", FileName, std::move(Error));
|
|
|
|
});
|
|
|
|
T.QueuePri = IndexFile;
|
2020-01-29 03:23:46 +08:00
|
|
|
T.Tag = std::string(filenameWithoutExtension(Cmd.Filename));
|
2019-07-11 21:34:38 +08:00
|
|
|
return T;
|
[clangd] Minimal implementation of automatic static index (not enabled).
Summary:
See tinyurl.com/clangd-automatic-index for design and goals.
Lots of limitations to keep this patch smallish, TODOs everywhere:
- no serialization to disk
- no changes to dynamic index, which now has a much simpler job
- no partitioning of symbols by file to avoid duplication of header symbols
- no reindexing of edited files
- only a single worker thread
- compilation database is slurped synchronously (doesn't scale)
- uses memindex, rebuilds after every file (should be dex, periodically)
It's not hooked up to ClangdServer/ClangdLSPServer yet: the layering
isn't clear (it should really be in ClangdServer, but ClangdLSPServer
has all the CDB interactions).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, jfb, cfe-commits
Differential Revision: https://reviews.llvm.org/D53032
llvm-svn: 344513
2018-10-15 21:34:10 +08:00
|
|
|
}
|
|
|
|
|
2019-07-12 18:18:42 +08:00
|
|
|
void BackgroundIndex::boostRelated(llvm::StringRef Path) {
|
[clangd] Add isHeaderFile helper.
Summary:
we have a few places using `ASTCtx.getLangOpts().IsHeaderFile` to
determine a header file, but it relies on "-x c-header" compiler flag,
if the compilation command doesn't have this flag, we will get a false
positive. We are encountering this issue in bazel build system.
To solve this problem, we infer the file from file name, actual changes will
come in follow-ups.
Reviewers: sammccall
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D70235
2019-11-13 23:30:07 +08:00
|
|
|
if (isHeaderFile(Path))
|
2019-07-12 18:18:42 +08:00
|
|
|
Queue.boost(filenameWithoutExtension(Path), IndexBoostedFile);
|
|
|
|
}
|
|
|
|
|
2019-01-15 17:03:33 +08:00
|
|
|
/// Given index results from a TU, only update symbols coming from files that
|
2019-07-04 17:52:12 +08:00
|
|
|
/// are different or missing from than \p ShardVersionsSnapshot. Also stores new
|
|
|
|
/// index information on IndexStorage.
|
|
|
|
void BackgroundIndex::update(
|
|
|
|
llvm::StringRef MainFile, IndexFileIn Index,
|
|
|
|
const llvm::StringMap<ShardVersion> &ShardVersionsSnapshot,
|
2019-07-19 18:18:52 +08:00
|
|
|
bool HadErrors) {
|
2020-04-08 22:14:53 +08:00
|
|
|
llvm::StringMap<FileDigest> FilesToUpdate;
|
2019-01-15 17:03:33 +08:00
|
|
|
for (const auto &IndexIt : *Index.Sources) {
|
|
|
|
const auto &IGN = IndexIt.getValue();
|
2019-07-04 17:52:12 +08:00
|
|
|
// Note that sources do not contain any information regarding missing
|
|
|
|
// headers, since we don't even know what absolute path they should fall in.
|
2020-04-08 22:14:53 +08:00
|
|
|
auto AbsPath = llvm::cantFail(URI::resolve(IGN.URI, MainFile),
|
|
|
|
"Failed to resovle URI");
|
2019-07-04 17:52:12 +08:00
|
|
|
const auto DigestIt = ShardVersionsSnapshot.find(AbsPath);
|
2020-04-05 14:28:11 +08:00
|
|
|
// File has different contents, or indexing was successful this time.
|
2019-07-04 17:52:12 +08:00
|
|
|
if (DigestIt == ShardVersionsSnapshot.end() ||
|
|
|
|
DigestIt->getValue().Digest != IGN.Digest ||
|
|
|
|
(DigestIt->getValue().HadErrors && !HadErrors))
|
2020-04-08 22:14:53 +08:00
|
|
|
FilesToUpdate[AbsPath] = IGN.Digest;
|
2019-06-15 10:26:47 +08:00
|
|
|
}
|
2018-11-06 18:55:21 +08:00
|
|
|
|
2020-04-08 22:14:53 +08:00
|
|
|
// Shard slabs into files.
|
|
|
|
FileShardedIndex ShardedIndex(std::move(Index), MainFile);
|
2019-07-04 17:51:43 +08:00
|
|
|
|
2020-04-08 22:14:53 +08:00
|
|
|
// Build and store new slabs for each updated file.
|
|
|
|
for (const auto &FileIt : FilesToUpdate) {
|
|
|
|
PathRef Path = FileIt.first();
|
|
|
|
auto IF = ShardedIndex.getShard(Path);
|
2019-07-19 18:18:52 +08:00
|
|
|
|
|
|
|
// Only store command line hash for main files of the TU, since our
|
|
|
|
// current model keeps only one version of a header file.
|
2020-04-08 22:14:53 +08:00
|
|
|
if (Path != MainFile)
|
|
|
|
IF.Cmd.reset();
|
2019-07-19 18:18:52 +08:00
|
|
|
|
2020-04-08 22:14:53 +08:00
|
|
|
// We need to store shards before updating the index, since the latter
|
|
|
|
// consumes slabs.
|
|
|
|
// FIXME: Also skip serializing the shard if it is already up-to-date.
|
|
|
|
if (auto Error = IndexStorageFactory(Path)->storeShard(Path, IF))
|
2019-07-19 18:18:52 +08:00
|
|
|
elog("Failed to write background-index shard for file {0}: {1}", Path,
|
|
|
|
std::move(Error));
|
2019-07-04 17:51:43 +08:00
|
|
|
|
2019-01-11 01:03:04 +08:00
|
|
|
{
|
2019-07-04 17:52:12 +08:00
|
|
|
std::lock_guard<std::mutex> Lock(ShardVersionsMu);
|
2020-04-08 22:14:53 +08:00
|
|
|
const auto &Hash = FileIt.getValue();
|
2019-07-04 17:52:12 +08:00
|
|
|
auto DigestIt = ShardVersions.try_emplace(Path);
|
|
|
|
ShardVersion &SV = DigestIt.first->second;
|
|
|
|
// Skip if file is already up to date, unless previous index was broken
|
|
|
|
// and this one is not.
|
|
|
|
if (!DigestIt.second && SV.Digest == Hash && SV.HadErrors && !HadErrors)
|
2019-01-11 01:03:04 +08:00
|
|
|
continue;
|
2019-07-04 17:52:12 +08:00
|
|
|
SV.Digest = Hash;
|
|
|
|
SV.HadErrors = HadErrors;
|
|
|
|
|
2019-01-11 01:03:04 +08:00
|
|
|
// This can override a newer version that is added in another thread, if
|
|
|
|
// this thread sees the older version but finishes later. This should be
|
|
|
|
// rare in practice.
|
2020-04-08 22:14:53 +08:00
|
|
|
IndexedSymbols.update(
|
|
|
|
Path, std::make_unique<SymbolSlab>(std::move(*IF.Symbols)),
|
|
|
|
std::make_unique<RefSlab>(std::move(*IF.Refs)),
|
|
|
|
std::make_unique<RelationSlab>(std::move(*IF.Relations)),
|
|
|
|
Path == MainFile);
|
2019-01-11 01:03:04 +08:00
|
|
|
}
|
2018-11-06 18:55:21 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-19 18:18:52 +08:00
|
|
|
llvm::Error BackgroundIndex::index(tooling::CompileCommand Cmd) {
|
[clangd] Minimal implementation of automatic static index (not enabled).
Summary:
See tinyurl.com/clangd-automatic-index for design and goals.
Lots of limitations to keep this patch smallish, TODOs everywhere:
- no serialization to disk
- no changes to dynamic index, which now has a much simpler job
- no partitioning of symbols by file to avoid duplication of header symbols
- no reindexing of edited files
- only a single worker thread
- compilation database is slurped synchronously (doesn't scale)
- uses memindex, rebuilds after every file (should be dex, periodically)
It's not hooked up to ClangdServer/ClangdLSPServer yet: the layering
isn't clear (it should really be in ClangdServer, but ClangdLSPServer
has all the CDB interactions).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, jfb, cfe-commits
Differential Revision: https://reviews.llvm.org/D53032
llvm-svn: 344513
2018-10-15 21:34:10 +08:00
|
|
|
trace::Span Tracer("BackgroundIndex");
|
|
|
|
SPAN_ATTACH(Tracer, "file", Cmd.Filename);
|
2019-01-11 01:03:04 +08:00
|
|
|
auto AbsolutePath = getAbsolutePath(Cmd);
|
[clangd] Minimal implementation of automatic static index (not enabled).
Summary:
See tinyurl.com/clangd-automatic-index for design and goals.
Lots of limitations to keep this patch smallish, TODOs everywhere:
- no serialization to disk
- no changes to dynamic index, which now has a much simpler job
- no partitioning of symbols by file to avoid duplication of header symbols
- no reindexing of edited files
- only a single worker thread
- compilation database is slurped synchronously (doesn't scale)
- uses memindex, rebuilds after every file (should be dex, periodically)
It's not hooked up to ClangdServer/ClangdLSPServer yet: the layering
isn't clear (it should really be in ClangdServer, but ClangdLSPServer
has all the CDB interactions).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, jfb, cfe-commits
Differential Revision: https://reviews.llvm.org/D53032
llvm-svn: 344513
2018-10-15 21:34:10 +08:00
|
|
|
|
|
|
|
auto FS = FSProvider.getFileSystem();
|
|
|
|
auto Buf = FS->getBufferForFile(AbsolutePath);
|
|
|
|
if (!Buf)
|
2019-01-07 23:45:19 +08:00
|
|
|
return llvm::errorCodeToError(Buf.getError());
|
2018-11-06 18:55:21 +08:00
|
|
|
auto Hash = digest(Buf->get()->getBuffer());
|
|
|
|
|
2019-07-04 17:52:12 +08:00
|
|
|
// Take a snapshot of the versions to avoid locking for each file in the TU.
|
|
|
|
llvm::StringMap<ShardVersion> ShardVersionsSnapshot;
|
2018-11-06 18:55:21 +08:00
|
|
|
{
|
2019-07-04 17:52:12 +08:00
|
|
|
std::lock_guard<std::mutex> Lock(ShardVersionsMu);
|
|
|
|
ShardVersionsSnapshot = ShardVersions;
|
[clangd] Minimal implementation of automatic static index (not enabled).
Summary:
See tinyurl.com/clangd-automatic-index for design and goals.
Lots of limitations to keep this patch smallish, TODOs everywhere:
- no serialization to disk
- no changes to dynamic index, which now has a much simpler job
- no partitioning of symbols by file to avoid duplication of header symbols
- no reindexing of edited files
- only a single worker thread
- compilation database is slurped synchronously (doesn't scale)
- uses memindex, rebuilds after every file (should be dex, periodically)
It's not hooked up to ClangdServer/ClangdLSPServer yet: the layering
isn't clear (it should really be in ClangdServer, but ClangdLSPServer
has all the CDB interactions).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, jfb, cfe-commits
Differential Revision: https://reviews.llvm.org/D53032
llvm-svn: 344513
2018-10-15 21:34:10 +08:00
|
|
|
}
|
|
|
|
|
2019-01-19 01:04:26 +08:00
|
|
|
vlog("Indexing {0} (digest:={1})", Cmd.Filename, llvm::toHex(Hash));
|
[clangd] Minimal implementation of automatic static index (not enabled).
Summary:
See tinyurl.com/clangd-automatic-index for design and goals.
Lots of limitations to keep this patch smallish, TODOs everywhere:
- no serialization to disk
- no changes to dynamic index, which now has a much simpler job
- no partitioning of symbols by file to avoid duplication of header symbols
- no reindexing of edited files
- only a single worker thread
- compilation database is slurped synchronously (doesn't scale)
- uses memindex, rebuilds after every file (should be dex, periodically)
It's not hooked up to ClangdServer/ClangdLSPServer yet: the layering
isn't clear (it should really be in ClangdServer, but ClangdLSPServer
has all the CDB interactions).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, jfb, cfe-commits
Differential Revision: https://reviews.llvm.org/D53032
llvm-svn: 344513
2018-10-15 21:34:10 +08:00
|
|
|
ParseInputs Inputs;
|
|
|
|
Inputs.FS = std::move(FS);
|
|
|
|
Inputs.FS->setCurrentWorkingDirectory(Cmd.Directory);
|
|
|
|
Inputs.CompileCommand = std::move(Cmd);
|
[clangd] Surface errors from command-line parsing
Summary:
Those errors are exposed at the first character of a file,
for a lack of a better place.
Previously, all errors were stored inside the AST and report
accordingly. However, errors in command-line argument parsing could
result in failure to produce the AST, so we need an alternative ways to
report those errors.
We take the following approach in this patch:
- buildCompilerInvocation() now requires an explicit DiagnosticConsumer.
- TUScheduler and TestTU now collect the diagnostics produced when
parsing command line arguments.
If pasing of the AST failed, diagnostics are reported via a new
ParsingCallbacks::onFailedAST method.
If parsing of the AST succeeded, any errors produced during
command-line parsing are stored alongside the AST inside the
ParsedAST instance and reported as previously by calling the
ParsingCallbacks::onMainAST method;
- The client code that uses ClangdServer's DiagnosticConsumer
does not need to change, it will receive new diagnostics in the
onDiagnosticsReady() callback
Errors produced when parsing command-line arguments are collected using
the same StoreDiags class that is used to collect all other errors. They
are recognized by their location being invalid. IIUC, the location is
invalid as there is no source manager at this point, it is created at a
later stage.
Although technically we might also get diagnostics that mention the
command-line arguments FileID with after the source manager was created
(and they have valid source locations), we choose to not handle those
and they are dropped as not coming from the main file. AFAICT, those
diagnostics should always be notes, therefore it's safe to drop them
without loosing too much information.
Reviewers: kadircet
Reviewed By: kadircet
Subscribers: nridge, javed.absar, MaskRay, jkorous, arphaman, cfe-commits, gribozavr
Tags: #clang
Differential Revision: https://reviews.llvm.org/D66759
llvm-svn: 370177
2019-08-28 17:24:55 +08:00
|
|
|
IgnoreDiagnostics IgnoreDiags;
|
|
|
|
auto CI = buildCompilerInvocation(Inputs, IgnoreDiags);
|
[clangd] Minimal implementation of automatic static index (not enabled).
Summary:
See tinyurl.com/clangd-automatic-index for design and goals.
Lots of limitations to keep this patch smallish, TODOs everywhere:
- no serialization to disk
- no changes to dynamic index, which now has a much simpler job
- no partitioning of symbols by file to avoid duplication of header symbols
- no reindexing of edited files
- only a single worker thread
- compilation database is slurped synchronously (doesn't scale)
- uses memindex, rebuilds after every file (should be dex, periodically)
It's not hooked up to ClangdServer/ClangdLSPServer yet: the layering
isn't clear (it should really be in ClangdServer, but ClangdLSPServer
has all the CDB interactions).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, jfb, cfe-commits
Differential Revision: https://reviews.llvm.org/D53032
llvm-svn: 344513
2018-10-15 21:34:10 +08:00
|
|
|
if (!CI)
|
2019-01-07 23:45:19 +08:00
|
|
|
return llvm::createStringError(llvm::inconvertibleErrorCode(),
|
|
|
|
"Couldn't build compiler invocation");
|
2019-04-04 20:56:03 +08:00
|
|
|
auto Clang = prepareCompilerInstance(std::move(CI), /*Preamble=*/nullptr,
|
|
|
|
std::move(*Buf), Inputs.FS, IgnoreDiags);
|
[clangd] Minimal implementation of automatic static index (not enabled).
Summary:
See tinyurl.com/clangd-automatic-index for design and goals.
Lots of limitations to keep this patch smallish, TODOs everywhere:
- no serialization to disk
- no changes to dynamic index, which now has a much simpler job
- no partitioning of symbols by file to avoid duplication of header symbols
- no reindexing of edited files
- only a single worker thread
- compilation database is slurped synchronously (doesn't scale)
- uses memindex, rebuilds after every file (should be dex, periodically)
It's not hooked up to ClangdServer/ClangdLSPServer yet: the layering
isn't clear (it should really be in ClangdServer, but ClangdLSPServer
has all the CDB interactions).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, jfb, cfe-commits
Differential Revision: https://reviews.llvm.org/D53032
llvm-svn: 344513
2018-10-15 21:34:10 +08:00
|
|
|
if (!Clang)
|
2019-01-07 23:45:19 +08:00
|
|
|
return llvm::createStringError(llvm::inconvertibleErrorCode(),
|
|
|
|
"Couldn't build compiler instance");
|
[clangd] Minimal implementation of automatic static index (not enabled).
Summary:
See tinyurl.com/clangd-automatic-index for design and goals.
Lots of limitations to keep this patch smallish, TODOs everywhere:
- no serialization to disk
- no changes to dynamic index, which now has a much simpler job
- no partitioning of symbols by file to avoid duplication of header symbols
- no reindexing of edited files
- only a single worker thread
- compilation database is slurped synchronously (doesn't scale)
- uses memindex, rebuilds after every file (should be dex, periodically)
It's not hooked up to ClangdServer/ClangdLSPServer yet: the layering
isn't clear (it should really be in ClangdServer, but ClangdLSPServer
has all the CDB interactions).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, jfb, cfe-commits
Differential Revision: https://reviews.llvm.org/D53032
llvm-svn: 344513
2018-10-15 21:34:10 +08:00
|
|
|
|
|
|
|
SymbolCollector::Options IndexOpts;
|
2019-07-04 17:52:12 +08:00
|
|
|
// Creates a filter to not collect index results from files with unchanged
|
|
|
|
// digests.
|
|
|
|
IndexOpts.FileFilter = [&ShardVersionsSnapshot](const SourceManager &SM,
|
|
|
|
FileID FID) {
|
|
|
|
const auto *F = SM.getFileEntryForID(FID);
|
|
|
|
if (!F)
|
|
|
|
return false; // Skip invalid files.
|
|
|
|
auto AbsPath = getCanonicalPath(F, SM);
|
|
|
|
if (!AbsPath)
|
|
|
|
return false; // Skip files without absolute path.
|
|
|
|
auto Digest = digestFile(SM, FID);
|
|
|
|
if (!Digest)
|
|
|
|
return false;
|
|
|
|
auto D = ShardVersionsSnapshot.find(*AbsPath);
|
|
|
|
if (D != ShardVersionsSnapshot.end() && D->second.Digest == Digest &&
|
|
|
|
!D->second.HadErrors)
|
|
|
|
return false; // Skip files that haven't changed, without errors.
|
|
|
|
return true;
|
|
|
|
};
|
|
|
|
|
2018-12-04 19:31:57 +08:00
|
|
|
IndexFileIn Index;
|
[clangd] Minimal implementation of automatic static index (not enabled).
Summary:
See tinyurl.com/clangd-automatic-index for design and goals.
Lots of limitations to keep this patch smallish, TODOs everywhere:
- no serialization to disk
- no changes to dynamic index, which now has a much simpler job
- no partitioning of symbols by file to avoid duplication of header symbols
- no reindexing of edited files
- only a single worker thread
- compilation database is slurped synchronously (doesn't scale)
- uses memindex, rebuilds after every file (should be dex, periodically)
It's not hooked up to ClangdServer/ClangdLSPServer yet: the layering
isn't clear (it should really be in ClangdServer, but ClangdLSPServer
has all the CDB interactions).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, jfb, cfe-commits
Differential Revision: https://reviews.llvm.org/D53032
llvm-svn: 344513
2018-10-15 21:34:10 +08:00
|
|
|
auto Action = createStaticIndexingAction(
|
2018-12-04 19:31:57 +08:00
|
|
|
IndexOpts, [&](SymbolSlab S) { Index.Symbols = std::move(S); },
|
|
|
|
[&](RefSlab R) { Index.Refs = std::move(R); },
|
2019-06-15 10:26:47 +08:00
|
|
|
[&](RelationSlab R) { Index.Relations = std::move(R); },
|
2018-12-04 19:31:57 +08:00
|
|
|
[&](IncludeGraph IG) { Index.Sources = std::move(IG); });
|
[clangd] Minimal implementation of automatic static index (not enabled).
Summary:
See tinyurl.com/clangd-automatic-index for design and goals.
Lots of limitations to keep this patch smallish, TODOs everywhere:
- no serialization to disk
- no changes to dynamic index, which now has a much simpler job
- no partitioning of symbols by file to avoid duplication of header symbols
- no reindexing of edited files
- only a single worker thread
- compilation database is slurped synchronously (doesn't scale)
- uses memindex, rebuilds after every file (should be dex, periodically)
It's not hooked up to ClangdServer/ClangdLSPServer yet: the layering
isn't clear (it should really be in ClangdServer, but ClangdLSPServer
has all the CDB interactions).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, jfb, cfe-commits
Differential Revision: https://reviews.llvm.org/D53032
llvm-svn: 344513
2018-10-15 21:34:10 +08:00
|
|
|
|
|
|
|
// We're going to run clang here, and it could potentially crash.
|
|
|
|
// We could use CrashRecoveryContext to try to make indexing crashes nonfatal,
|
|
|
|
// but the leaky "recovery" is pretty scary too in a long-running process.
|
|
|
|
// If crashes are a real problem, maybe we should fork a child process.
|
|
|
|
|
|
|
|
const FrontendInputFile &Input = Clang->getFrontendOpts().Inputs.front();
|
|
|
|
if (!Action->BeginSourceFile(*Clang, Input))
|
2019-01-07 23:45:19 +08:00
|
|
|
return llvm::createStringError(llvm::inconvertibleErrorCode(),
|
|
|
|
"BeginSourceFile() failed");
|
2019-06-27 03:50:12 +08:00
|
|
|
if (llvm::Error Err = Action->Execute())
|
|
|
|
return Err;
|
|
|
|
|
[clangd] Minimal implementation of automatic static index (not enabled).
Summary:
See tinyurl.com/clangd-automatic-index for design and goals.
Lots of limitations to keep this patch smallish, TODOs everywhere:
- no serialization to disk
- no changes to dynamic index, which now has a much simpler job
- no partitioning of symbols by file to avoid duplication of header symbols
- no reindexing of edited files
- only a single worker thread
- compilation database is slurped synchronously (doesn't scale)
- uses memindex, rebuilds after every file (should be dex, periodically)
It's not hooked up to ClangdServer/ClangdLSPServer yet: the layering
isn't clear (it should really be in ClangdServer, but ClangdLSPServer
has all the CDB interactions).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, jfb, cfe-commits
Differential Revision: https://reviews.llvm.org/D53032
llvm-svn: 344513
2018-10-15 21:34:10 +08:00
|
|
|
Action->EndSourceFile();
|
2018-12-14 20:39:08 +08:00
|
|
|
|
2019-07-04 17:51:53 +08:00
|
|
|
Index.Cmd = Inputs.CompileCommand;
|
2019-01-11 01:03:04 +08:00
|
|
|
assert(Index.Symbols && Index.Refs && Index.Sources &&
|
|
|
|
"Symbols, Refs and Sources must be set.");
|
[clangd] Minimal implementation of automatic static index (not enabled).
Summary:
See tinyurl.com/clangd-automatic-index for design and goals.
Lots of limitations to keep this patch smallish, TODOs everywhere:
- no serialization to disk
- no changes to dynamic index, which now has a much simpler job
- no partitioning of symbols by file to avoid duplication of header symbols
- no reindexing of edited files
- only a single worker thread
- compilation database is slurped synchronously (doesn't scale)
- uses memindex, rebuilds after every file (should be dex, periodically)
It's not hooked up to ClangdServer/ClangdLSPServer yet: the layering
isn't clear (it should really be in ClangdServer, but ClangdLSPServer
has all the CDB interactions).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, jfb, cfe-commits
Differential Revision: https://reviews.llvm.org/D53032
llvm-svn: 344513
2018-10-15 21:34:10 +08:00
|
|
|
|
2018-12-04 19:31:57 +08:00
|
|
|
log("Indexed {0} ({1} symbols, {2} refs, {3} files)",
|
|
|
|
Inputs.CompileCommand.Filename, Index.Symbols->size(),
|
|
|
|
Index.Refs->numRefs(), Index.Sources->size());
|
|
|
|
SPAN_ATTACH(Tracer, "symbols", int(Index.Symbols->size()));
|
|
|
|
SPAN_ATTACH(Tracer, "refs", int(Index.Refs->numRefs()));
|
|
|
|
SPAN_ATTACH(Tracer, "sources", int(Index.Sources->size()));
|
2018-11-28 00:08:53 +08:00
|
|
|
|
2019-07-04 17:51:43 +08:00
|
|
|
bool HadErrors = Clang->hasDiagnostics() &&
|
|
|
|
Clang->getDiagnostics().hasUncompilableErrorOccurred();
|
2019-07-04 17:52:04 +08:00
|
|
|
if (HadErrors) {
|
|
|
|
log("Failed to compile {0}, index may be incomplete", AbsolutePath);
|
|
|
|
for (auto &It : *Index.Sources)
|
|
|
|
It.second.Flags |= IncludeGraphNode::SourceFlag::HadErrors;
|
|
|
|
}
|
2019-07-19 18:18:52 +08:00
|
|
|
update(AbsolutePath, std::move(Index), ShardVersionsSnapshot, HadErrors);
|
[clangd] Minimal implementation of automatic static index (not enabled).
Summary:
See tinyurl.com/clangd-automatic-index for design and goals.
Lots of limitations to keep this patch smallish, TODOs everywhere:
- no serialization to disk
- no changes to dynamic index, which now has a much simpler job
- no partitioning of symbols by file to avoid duplication of header symbols
- no reindexing of edited files
- only a single worker thread
- compilation database is slurped synchronously (doesn't scale)
- uses memindex, rebuilds after every file (should be dex, periodically)
It's not hooked up to ClangdServer/ClangdLSPServer yet: the layering
isn't clear (it should really be in ClangdServer, but ClangdLSPServer
has all the CDB interactions).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, jfb, cfe-commits
Differential Revision: https://reviews.llvm.org/D53032
llvm-svn: 344513
2018-10-15 21:34:10 +08:00
|
|
|
|
[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
|
|
|
Rebuilder.indexedTU();
|
2019-01-07 23:45:19 +08:00
|
|
|
return llvm::Error::success();
|
[clangd] Minimal implementation of automatic static index (not enabled).
Summary:
See tinyurl.com/clangd-automatic-index for design and goals.
Lots of limitations to keep this patch smallish, TODOs everywhere:
- no serialization to disk
- no changes to dynamic index, which now has a much simpler job
- no partitioning of symbols by file to avoid duplication of header symbols
- no reindexing of edited files
- only a single worker thread
- compilation database is slurped synchronously (doesn't scale)
- uses memindex, rebuilds after every file (should be dex, periodically)
It's not hooked up to ClangdServer/ClangdLSPServer yet: the layering
isn't clear (it should really be in ClangdServer, but ClangdLSPServer
has all the CDB interactions).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, jfb, cfe-commits
Differential Revision: https://reviews.llvm.org/D53032
llvm-svn: 344513
2018-10-15 21:34:10 +08:00
|
|
|
}
|
|
|
|
|
2019-07-19 18:18:52 +08:00
|
|
|
// Restores shards for \p MainFiles from index storage. Then checks staleness of
|
|
|
|
// those shards and returns a list of TUs that needs to be indexed to update
|
|
|
|
// staleness.
|
|
|
|
std::vector<tooling::CompileCommand>
|
|
|
|
BackgroundIndex::loadProject(std::vector<std::string> MainFiles) {
|
|
|
|
std::vector<tooling::CompileCommand> NeedsReIndexing;
|
2019-01-11 01:03:04 +08:00
|
|
|
|
2019-07-19 18:18:52 +08:00
|
|
|
Rebuilder.startLoading();
|
|
|
|
// Load shards for all of the mainfiles.
|
|
|
|
const std::vector<LoadedShard> Result =
|
|
|
|
loadIndexShards(MainFiles, IndexStorageFactory, CDB);
|
|
|
|
size_t LoadedShards = 0;
|
2019-01-11 01:03:04 +08:00
|
|
|
{
|
2019-07-19 18:18:52 +08:00
|
|
|
// Update in-memory state.
|
2019-07-04 17:52:12 +08:00
|
|
|
std::lock_guard<std::mutex> Lock(ShardVersionsMu);
|
2019-07-19 18:18:52 +08:00
|
|
|
for (auto &LS : Result) {
|
|
|
|
if (!LS.Shard)
|
|
|
|
continue;
|
2019-01-11 01:03:04 +08:00
|
|
|
auto SS =
|
2019-07-19 18:18:52 +08:00
|
|
|
LS.Shard->Symbols
|
2019-08-15 07:52:23 +08:00
|
|
|
? std::make_unique<SymbolSlab>(std::move(*LS.Shard->Symbols))
|
2019-01-11 01:03:04 +08:00
|
|
|
: nullptr;
|
2019-07-19 18:18:52 +08:00
|
|
|
auto RS = LS.Shard->Refs
|
2019-08-15 07:52:23 +08:00
|
|
|
? std::make_unique<RefSlab>(std::move(*LS.Shard->Refs))
|
2019-01-11 01:03:04 +08:00
|
|
|
: nullptr;
|
2019-06-15 10:26:47 +08:00
|
|
|
auto RelS =
|
2019-07-19 18:18:52 +08:00
|
|
|
LS.Shard->Relations
|
2019-08-15 07:52:23 +08:00
|
|
|
? std::make_unique<RelationSlab>(std::move(*LS.Shard->Relations))
|
2019-06-15 10:26:47 +08:00
|
|
|
: nullptr;
|
2019-07-19 18:18:52 +08:00
|
|
|
ShardVersion &SV = ShardVersions[LS.AbsolutePath];
|
|
|
|
SV.Digest = LS.Digest;
|
|
|
|
SV.HadErrors = LS.HadErrors;
|
|
|
|
++LoadedShards;
|
2019-07-04 17:52:12 +08:00
|
|
|
|
2019-07-19 18:18:52 +08:00
|
|
|
IndexedSymbols.update(LS.AbsolutePath, std::move(SS), std::move(RS),
|
|
|
|
std::move(RelS), LS.CountReferences);
|
2019-01-11 01:03:04 +08:00
|
|
|
}
|
|
|
|
}
|
2019-07-19 18:18:52 +08:00
|
|
|
Rebuilder.loadedShard(LoadedShards);
|
|
|
|
Rebuilder.doneLoading();
|
2019-01-11 01:03:04 +08:00
|
|
|
|
2019-07-19 18:18:52 +08:00
|
|
|
auto FS = FSProvider.getFileSystem();
|
|
|
|
llvm::DenseSet<PathRef> TUsToIndex;
|
|
|
|
// We'll accept data from stale shards, but ensure the files get reindexed
|
|
|
|
// soon.
|
|
|
|
for (auto &LS : Result) {
|
|
|
|
if (!shardIsStale(LS, FS.get()))
|
|
|
|
continue;
|
|
|
|
PathRef TUForFile = LS.DependentTU;
|
|
|
|
assert(!TUForFile.empty() && "File without a TU!");
|
|
|
|
|
|
|
|
// FIXME: Currently, we simply schedule indexing on a TU whenever any of
|
|
|
|
// its dependencies needs re-indexing. We might do it smarter by figuring
|
|
|
|
// out a minimal set of TUs that will cover all the stale dependencies.
|
|
|
|
// FIXME: Try looking at other TUs if no compile commands are available
|
|
|
|
// for this TU, i.e TU was deleted after we performed indexing.
|
|
|
|
TUsToIndex.insert(TUForFile);
|
|
|
|
}
|
2019-01-11 01:03:04 +08:00
|
|
|
|
2019-07-19 18:18:52 +08:00
|
|
|
for (PathRef TU : TUsToIndex) {
|
|
|
|
auto Cmd = CDB.getCompileCommand(TU);
|
2019-01-11 01:03:04 +08:00
|
|
|
if (!Cmd)
|
|
|
|
continue;
|
2019-07-19 18:18:52 +08:00
|
|
|
NeedsReIndexing.emplace_back(std::move(*Cmd));
|
2019-07-19 17:26:33 +08:00
|
|
|
}
|
2019-07-19 18:18:52 +08:00
|
|
|
|
2019-01-11 01:03:04 +08:00
|
|
|
return NeedsReIndexing;
|
|
|
|
}
|
|
|
|
|
[clangd] Minimal implementation of automatic static index (not enabled).
Summary:
See tinyurl.com/clangd-automatic-index for design and goals.
Lots of limitations to keep this patch smallish, TODOs everywhere:
- no serialization to disk
- no changes to dynamic index, which now has a much simpler job
- no partitioning of symbols by file to avoid duplication of header symbols
- no reindexing of edited files
- only a single worker thread
- compilation database is slurped synchronously (doesn't scale)
- uses memindex, rebuilds after every file (should be dex, periodically)
It's not hooked up to ClangdServer/ClangdLSPServer yet: the layering
isn't clear (it should really be in ClangdServer, but ClangdLSPServer
has all the CDB interactions).
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, jfb, cfe-commits
Differential Revision: https://reviews.llvm.org/D53032
llvm-svn: 344513
2018-10-15 21:34:10 +08:00
|
|
|
} // namespace clangd
|
|
|
|
} // namespace clang
|