1 //===--- TUScheduler.cpp -----------------------------------------*-C++-*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
8 // TUScheduler manages a worker per active file. This ASTWorker processes
9 // updates (modifications to file contents) and reads (actions performed on
10 // preamble/AST) to the file.
12 // Each ASTWorker owns a dedicated thread to process updates and reads to the
13 // relevant file. Any request gets queued in FIFO order to be processed by that
16 // An update request replaces current praser inputs to ensure any subsequent
17 // read sees the version of the file they were requested. It will also issue a
18 // build for new inputs.
20 // ASTWorker processes the file in two parts, a preamble and a main-file
21 // section. A preamble can be reused between multiple versions of the file until
22 // invalidated by a modification to a header, compile commands or modification
23 // to relevant part of the current file. Such a preamble is called compatible.
24 // An update is considered dead if no read was issued for that version and
25 // diagnostics weren't requested by client or could be generated for a later
26 // version of the file. ASTWorker eliminates such requests as they are
29 // In the presence of stale (non-compatible) preambles, ASTWorker won't publish
30 // diagnostics for update requests. Read requests will be served with ASTs build
31 // with stale preambles, unless the read is picky and requires a compatible
32 // preamble. In such cases it will block until new preamble is built.
34 // ASTWorker owns a PreambleThread for building preambles. If the preamble gets
35 // invalidated by an update request, a new build will be requested on
36 // PreambleThread. Since PreambleThread only receives requests for newer
37 // versions of the file, in case of multiple requests it will only build the
38 // last one and skip requests in between. Unless client force requested
39 // diagnostics(WantDiagnostics::Yes).
41 // When a new preamble is built, a "golden" AST is immediately built from that
42 // version of the file. This ensures diagnostics get updated even if the queue
45 // Some read requests might just need preamble. Since preambles can be read
46 // concurrently, ASTWorker runs these requests on their own thread. These
47 // requests will receive latest build preamble, which might possibly be stale.
49 #include "TUScheduler.h"
50 #include "CompileCommands.h"
53 #include "Diagnostics.h"
54 #include "GlobalCompilationDatabase.h"
55 #include "ParsedAST.h"
57 #include "clang-include-cleaner/Record.h"
58 #include "support/Cancellation.h"
59 #include "support/Context.h"
60 #include "support/Logger.h"
61 #include "support/MemoryTree.h"
62 #include "support/Path.h"
63 #include "support/ThreadCrashReporter.h"
64 #include "support/Threading.h"
65 #include "support/Trace.h"
66 #include "clang/Basic/Stack.h"
67 #include "clang/Frontend/CompilerInvocation.h"
68 #include "clang/Tooling/CompilationDatabase.h"
69 #include "llvm/ADT/FunctionExtras.h"
70 #include "llvm/ADT/STLExtras.h"
71 #include "llvm/ADT/ScopeExit.h"
72 #include "llvm/ADT/SmallVector.h"
73 #include "llvm/ADT/StringExtras.h"
74 #include "llvm/ADT/StringRef.h"
75 #include "llvm/Support/Allocator.h"
76 #include "llvm/Support/Errc.h"
77 #include "llvm/Support/ErrorHandling.h"
78 #include "llvm/Support/FormatVariadic.h"
79 #include "llvm/Support/Path.h"
80 #include "llvm/Support/Threading.h"
81 #include "llvm/Support/raw_ostream.h"
85 #include <condition_variable>
93 #include <type_traits>
99 using std::chrono::steady_clock
;
102 // Tracks latency (in seconds) of FS operations done during a preamble build.
103 // build_type allows to split by expected VFS cache state (cold on first
104 // preamble, somewhat warm after that when building first preamble for new file,
105 // likely ~everything cached on preamble rebuild.
106 constexpr trace::Metric
107 PreambleBuildFilesystemLatency("preamble_fs_latency",
108 trace::Metric::Distribution
, "build_type");
109 // Tracks latency of FS operations done during a preamble build as a ratio of
110 // preamble build time. build_type is same as above.
111 constexpr trace::Metric
PreambleBuildFilesystemLatencyRatio(
112 "preamble_fs_latency_ratio", trace::Metric::Distribution
, "build_type");
114 constexpr trace::Metric
PreambleBuildSize("preamble_build_size",
115 trace::Metric::Distribution
);
116 constexpr trace::Metric
PreambleSerializedSize("preamble_serialized_size",
117 trace::Metric::Distribution
);
119 void reportPreambleBuild(const PreambleBuildStats
&Stats
,
120 bool IsFirstPreamble
) {
121 auto RecordWithLabel
= [&Stats
](llvm::StringRef Label
) {
122 PreambleBuildFilesystemLatency
.record(Stats
.FileSystemTime
, Label
);
123 if (Stats
.TotalBuildTime
> 0) // Avoid division by zero.
124 PreambleBuildFilesystemLatencyRatio
.record(
125 Stats
.FileSystemTime
/ Stats
.TotalBuildTime
, Label
);
128 static llvm::once_flag OnceFlag
;
129 llvm::call_once(OnceFlag
, [&] { RecordWithLabel("first_build"); });
130 RecordWithLabel(IsFirstPreamble
? "first_build_for_file" : "rebuild");
132 PreambleBuildSize
.record(Stats
.BuildSize
);
133 PreambleSerializedSize
.record(Stats
.SerializedSize
);
139 static clang::clangd::Key
<std::string
> FileBeingProcessed
;
141 std::optional
<llvm::StringRef
> TUScheduler::getFileBeingProcessedInContext() {
142 if (auto *File
= Context::current().get(FileBeingProcessed
))
143 return llvm::StringRef(*File
);
147 /// An LRU cache of idle ASTs.
148 /// Because we want to limit the overall number of these we retain, the cache
149 /// owns ASTs (and may evict them) while their workers are idle.
150 /// Workers borrow ASTs when active, and return them when done.
151 class TUScheduler::ASTCache
{
153 using Key
= const ASTWorker
*;
155 ASTCache(unsigned MaxRetainedASTs
) : MaxRetainedASTs(MaxRetainedASTs
) {}
157 /// Returns result of getUsedBytes() for the AST cached by \p K.
158 /// If no AST is cached, 0 is returned.
159 std::size_t getUsedBytes(Key K
) {
160 std::lock_guard
<std::mutex
> Lock(Mut
);
161 auto It
= findByKey(K
);
162 if (It
== LRU
.end() || !It
->second
)
164 return It
->second
->getUsedBytes();
167 /// Store the value in the pool, possibly removing the last used AST.
168 /// The value should not be in the pool when this function is called.
169 void put(Key K
, std::unique_ptr
<ParsedAST
> V
) {
170 std::unique_lock
<std::mutex
> Lock(Mut
);
171 assert(findByKey(K
) == LRU
.end());
173 LRU
.insert(LRU
.begin(), {K
, std::move(V
)});
174 if (LRU
.size() <= MaxRetainedASTs
)
176 // We're past the limit, remove the last element.
177 std::unique_ptr
<ParsedAST
> ForCleanup
= std::move(LRU
.back().second
);
179 // Run the expensive destructor outside the lock.
184 /// Returns the cached value for \p K, or std::nullopt if the value is not in
185 /// the cache anymore. If nullptr was cached for \p K, this function will
186 /// return a null unique_ptr wrapped into an optional.
187 /// If \p AccessMetric is set records whether there was a hit or miss.
188 std::optional
<std::unique_ptr
<ParsedAST
>>
189 take(Key K
, const trace::Metric
*AccessMetric
= nullptr) {
190 // Record metric after unlocking the mutex.
191 std::unique_lock
<std::mutex
> Lock(Mut
);
192 auto Existing
= findByKey(K
);
193 if (Existing
== LRU
.end()) {
195 AccessMetric
->record(1, "miss");
199 AccessMetric
->record(1, "hit");
200 std::unique_ptr
<ParsedAST
> V
= std::move(Existing
->second
);
202 // GCC 4.8 fails to compile `return V;`, as it tries to call the copy
203 // constructor of unique_ptr, so we call the move ctor explicitly to avoid
205 return std::optional
<std::unique_ptr
<ParsedAST
>>(std::move(V
));
209 using KVPair
= std::pair
<Key
, std::unique_ptr
<ParsedAST
>>;
211 std::vector
<KVPair
>::iterator
findByKey(Key K
) {
212 return llvm::find_if(LRU
, [K
](const KVPair
&P
) { return P
.first
== K
; });
216 unsigned MaxRetainedASTs
;
217 /// Items sorted in LRU order, i.e. first item is the most recently accessed
219 std::vector
<KVPair
> LRU
; /* GUARDED_BY(Mut) */
222 /// A map from header files to an opened "proxy" file that includes them.
223 /// If you open the header, the compile command from the proxy file is used.
225 /// This inclusion information could also naturally live in the index, but there
226 /// are advantages to using open files instead:
227 /// - it's easier to achieve a *stable* choice of proxy, which is important
228 /// to avoid invalidating the preamble
229 /// - context-sensitive flags for libraries with multiple configurations
230 /// (e.g. C++ stdlib sensitivity to -std version)
231 /// - predictable behavior, e.g. guarantees that go-to-def landing on a header
232 /// will have a suitable command available
233 /// - fewer scaling problems to solve (project include graphs are big!)
235 /// Implementation details:
236 /// - We only record this for mainfiles where the command was trustworthy
237 /// (i.e. not inferred). This avoids a bad inference "infecting" other files.
238 /// - Once we've picked a proxy file for a header, we stick with it until the
239 /// proxy file is invalidated *and* a new candidate proxy file is built.
240 /// Switching proxies is expensive, as the compile flags will (probably)
241 /// change and therefore we'll end up rebuilding the header's preamble.
242 /// - We don't capture the actual compile command, but just the filename we
243 /// should query to get it. This avoids getting out of sync with the CDB.
245 /// All methods are threadsafe. In practice, update() comes from preamble
246 /// threads, remove()s mostly from the main thread, and get() from ASTWorker.
247 /// Writes are rare and reads are cheap, so we don't expect much contention.
248 class TUScheduler::HeaderIncluderCache
{
249 // We should be a little careful how we store the include graph of open
250 // files, as each can have a large number of transitive headers.
251 // This representation is O(unique transitive source files).
252 llvm::BumpPtrAllocator Arena
;
254 llvm::StringRef MainFile
;
255 // Circular-linked-list of associations with the same mainFile.
256 // Null indicates that the mainfile was removed.
259 llvm::StringMap
<Association
, llvm::BumpPtrAllocator
&> HeaderToMain
;
260 llvm::StringMap
<Association
*, llvm::BumpPtrAllocator
&> MainToFirst
;
261 std::atomic
<size_t> UsedBytes
; // Updated after writes.
262 mutable std::mutex Mu
;
264 void invalidate(Association
*First
) {
265 Association
*Current
= First
;
267 Association
*Next
= Current
->Next
;
268 Current
->Next
= nullptr;
270 } while (Current
!= First
);
273 // Create the circular list and return the head of it.
274 Association
*associate(llvm::StringRef MainFile
,
275 llvm::ArrayRef
<std::string
> Headers
) {
276 Association
*First
= nullptr, *Prev
= nullptr;
277 for (const std::string
&Header
: Headers
) {
278 auto &Assoc
= HeaderToMain
[Header
];
280 continue; // Already has a valid association.
282 Assoc
.MainFile
= MainFile
;
293 void updateMemoryUsage() {
294 auto StringMapHeap
= [](const auto &Map
) {
295 // StringMap stores the hashtable on the heap.
296 // It contains pointers to the entries, and a hashcode for each.
297 return Map
.getNumBuckets() * (sizeof(void *) + sizeof(unsigned));
299 size_t Usage
= Arena
.getTotalMemory() + StringMapHeap(MainToFirst
) +
300 StringMapHeap(HeaderToMain
) + sizeof(*this);
301 UsedBytes
.store(Usage
, std::memory_order_release
);
305 HeaderIncluderCache() : HeaderToMain(Arena
), MainToFirst(Arena
) {
309 // Associate each header with MainFile (unless already associated).
310 // Headers not in the list will have their associations removed.
311 void update(PathRef MainFile
, llvm::ArrayRef
<std::string
> Headers
) {
312 std::lock_guard
<std::mutex
> Lock(Mu
);
313 auto It
= MainToFirst
.try_emplace(MainFile
, nullptr);
314 Association
*&First
= It
.first
->second
;
317 First
= associate(It
.first
->first(), Headers
);
321 // Mark MainFile as gone.
322 // This will *not* disassociate headers with MainFile immediately, but they
323 // will be eligible for association with other files that get update()d.
324 void remove(PathRef MainFile
) {
325 std::lock_guard
<std::mutex
> Lock(Mu
);
326 Association
*&First
= MainToFirst
[MainFile
];
331 // MainToFirst entry should stay alive, as Associations might be pointing at
335 /// Get the mainfile associated with Header, or the empty string if none.
336 std::string
get(PathRef Header
) const {
337 std::lock_guard
<std::mutex
> Lock(Mu
);
338 return HeaderToMain
.lookup(Header
).MainFile
.str();
341 size_t getUsedBytes() const {
342 return UsedBytes
.load(std::memory_order_acquire
);
348 bool isReliable(const tooling::CompileCommand
&Cmd
) {
349 return Cmd
.Heuristic
.empty();
352 /// Threadsafe manager for updating a TUStatus and emitting it after each
354 class SynchronizedTUStatus
{
356 SynchronizedTUStatus(PathRef FileName
, ParsingCallbacks
&Callbacks
)
357 : FileName(FileName
), Callbacks(Callbacks
) {}
359 void update(llvm::function_ref
<void(TUStatus
&)> Mutator
) {
360 std::lock_guard
<std::mutex
> Lock(StatusMu
);
365 /// Prevents emitting of further updates.
367 std::lock_guard
<std::mutex
> Lock(StatusMu
);
372 void emitStatusLocked() {
374 Callbacks
.onFileUpdated(FileName
, Status
);
381 bool CanPublish
= true;
382 ParsingCallbacks
&Callbacks
;
385 // An attempt to acquire resources for a task using PreambleThrottler.
386 // Initially it is unsatisfied, it (hopefully) becomes satisfied later but may
387 // be destroyed before then. Destruction releases all resources.
388 class PreambleThrottlerRequest
{
390 // The condition variable is signalled when the request is satisfied.
391 PreambleThrottlerRequest(llvm::StringRef Filename
,
392 PreambleThrottler
*Throttler
,
393 std::condition_variable
&CV
)
394 : Throttler(Throttler
),
395 Satisfied(Throttler
== nullptr) {
396 // If there is no throttler, this dummy request is always satisfied.
399 ID
= Throttler
->acquire(Filename
, [&] {
400 Satisfied
.store(true, std::memory_order_release
);
405 bool satisfied() const { return Satisfied
.load(std::memory_order_acquire
); }
407 // When the request is destroyed:
408 // - if resources are not yet obtained, stop trying to get them.
409 // - if resources were obtained, release them.
410 ~PreambleThrottlerRequest() {
412 Throttler
->release(ID
);
414 PreambleThrottlerRequest(const PreambleThrottlerRequest
&) = delete;
415 PreambleThrottlerRequest
&
416 operator=(const PreambleThrottlerRequest
&) = delete;
419 PreambleThrottler::RequestID ID
;
420 PreambleThrottler
*Throttler
;
421 std::atomic
<bool> Satisfied
= {false};
424 /// Responsible for building preambles. Whenever the thread is idle and the
425 /// preamble is outdated, it starts to build a fresh preamble from the latest
426 /// inputs. If RunSync is true, preambles are built synchronously in update()
428 class PreambleThread
{
430 PreambleThread(llvm::StringRef FileName
, ParsingCallbacks
&Callbacks
,
431 bool StorePreambleInMemory
, bool RunSync
,
432 PreambleThrottler
*Throttler
, SynchronizedTUStatus
&Status
,
433 TUScheduler::HeaderIncluderCache
&HeaderIncluders
,
435 : FileName(FileName
), Callbacks(Callbacks
),
436 StoreInMemory(StorePreambleInMemory
), RunSync(RunSync
),
437 Throttler(Throttler
), Status(Status
), ASTPeer(AW
),
438 HeaderIncluders(HeaderIncluders
) {}
440 /// It isn't guaranteed that each requested version will be built. If there
441 /// are multiple update requests while building a preamble, only the last one
443 void update(std::unique_ptr
<CompilerInvocation
> CI
, ParseInputs PI
,
444 std::vector
<Diag
> CIDiags
, WantDiagnostics WantDiags
) {
445 Request Req
= {std::move(CI
), std::move(PI
), std::move(CIDiags
), WantDiags
,
446 Context::current().clone()};
448 build(std::move(Req
));
449 Status
.update([](TUStatus
&Status
) {
450 Status
.PreambleActivity
= PreambleAction::Idle
;
455 std::unique_lock
<std::mutex
> Lock(Mutex
);
456 // If NextReq was requested with WantDiagnostics::Yes we cannot just drop
457 // that on the floor. Block until we start building it. This won't
458 // dead-lock as we are blocking the caller thread, while builds continue
459 // on preamble thread.
460 ReqCV
.wait(Lock
, [this] {
461 return !NextReq
|| NextReq
->WantDiags
!= WantDiagnostics::Yes
;
463 NextReq
= std::move(Req
);
465 // Let the worker thread know there's a request, notify_one is safe as there
466 // should be a single worker thread waiting on it.
471 // We mark the current as the stack bottom so that clang running on this
472 // thread can notice the stack usage and prevent stack overflow with best
473 // efforts. Same applies to other calls thoughout clangd.
474 clang::noteBottomOfStack();
476 std::optional
<PreambleThrottlerRequest
> Throttle
;
478 std::unique_lock
<std::mutex
> Lock(Mutex
);
479 assert(!CurrentReq
&& "Already processing a request?");
480 // Wait until stop is called or there is a request.
481 ReqCV
.wait(Lock
, [&] { return NextReq
|| Done
; });
486 Throttle
.emplace(FileName
, Throttler
, ReqCV
);
487 std::optional
<trace::Span
> Tracer
;
488 // If acquire succeeded synchronously, avoid status jitter.
489 if (!Throttle
->satisfied()) {
490 Tracer
.emplace("PreambleThrottle");
491 Status
.update([&](TUStatus
&Status
) {
492 Status
.PreambleActivity
= PreambleAction::Queued
;
495 ReqCV
.wait(Lock
, [&] { return Throttle
->satisfied() || Done
; });
499 // While waiting for the throttler, the request may have been updated!
500 // That's fine though, there's still guaranteed to be some request.
502 CurrentReq
= std::move(*NextReq
);
507 WithContext
Guard(std::move(CurrentReq
->Ctx
));
508 // Note that we don't make use of the ContextProvider here.
509 // Preamble tasks are always scheduled by ASTWorker tasks, and we
510 // reuse the context/config that was created at that level.
512 // Build the preamble and let the waiters know about it.
513 build(std::move(*CurrentReq
));
515 // Releasing the throttle before destroying the request assists testing.
517 bool IsEmpty
= false;
519 std::lock_guard
<std::mutex
> Lock(Mutex
);
524 // We don't perform this above, before waiting for a request to make
525 // tests more deterministic. As there can be a race between this thread
526 // and client thread(clangdserver).
527 Status
.update([](TUStatus
&Status
) {
528 Status
.PreambleActivity
= PreambleAction::Idle
;
533 dlog("Preamble worker for {0} stopped", FileName
);
536 /// Signals the run loop to exit.
538 dlog("Preamble worker for {0} received stop", FileName
);
540 std::lock_guard
<std::mutex
> Lock(Mutex
);
544 // Let the worker thread know that it should stop.
548 bool blockUntilIdle(Deadline Timeout
) const {
549 std::unique_lock
<std::mutex
> Lock(Mutex
);
550 return wait(Lock
, ReqCV
, Timeout
, [&] { return !NextReq
&& !CurrentReq
; });
554 /// Holds inputs required for building a preamble. CI is guaranteed to be
557 std::unique_ptr
<CompilerInvocation
> CI
;
559 std::vector
<Diag
> CIDiags
;
560 WantDiagnostics WantDiags
;
565 std::lock_guard
<std::mutex
> Lock(Mutex
);
569 /// Builds a preamble for \p Req, might reuse LatestBuild if possible.
570 /// Notifies ASTWorker after build finishes.
571 void build(Request Req
);
573 mutable std::mutex Mutex
;
574 bool Done
= false; /* GUARDED_BY(Mutex) */
575 std::optional
<Request
> NextReq
; /* GUARDED_BY(Mutex) */
576 std::optional
<Request
> CurrentReq
; /* GUARDED_BY(Mutex) */
577 // Signaled whenever a thread populates NextReq or worker thread builds a
579 mutable std::condition_variable ReqCV
; /* GUARDED_BY(Mutex) */
580 // Accessed only by preamble thread.
581 std::shared_ptr
<const PreambleData
> LatestBuild
;
584 ParsingCallbacks
&Callbacks
;
585 const bool StoreInMemory
;
587 PreambleThrottler
*Throttler
;
589 SynchronizedTUStatus
&Status
;
591 TUScheduler::HeaderIncluderCache
&HeaderIncluders
;
594 class ASTWorkerHandle
;
596 /// Owns one instance of the AST, schedules updates and reads of it.
597 /// Also responsible for building and providing access to the preamble.
598 /// Each ASTWorker processes the async requests sent to it on a separate
599 /// dedicated thread.
600 /// The ASTWorker that manages the AST is shared by both the processing thread
601 /// and the TUScheduler. The TUScheduler should discard an ASTWorker when
602 /// remove() is called, but its thread may be busy and we don't want to block.
603 /// So the workers are accessed via an ASTWorkerHandle. Destroying the handle
604 /// signals the worker to exit its run loop and gives up shared ownership of the
607 friend class ASTWorkerHandle
;
608 ASTWorker(PathRef FileName
, const GlobalCompilationDatabase
&CDB
,
609 TUScheduler::ASTCache
&LRUCache
,
610 TUScheduler::HeaderIncluderCache
&HeaderIncluders
,
611 Semaphore
&Barrier
, bool RunSync
, const TUScheduler::Options
&Opts
,
612 ParsingCallbacks
&Callbacks
);
615 /// Create a new ASTWorker and return a handle to it.
616 /// The processing thread is spawned using \p Tasks. However, when \p Tasks
617 /// is null, all requests will be processed on the calling thread
618 /// synchronously instead. \p Barrier is acquired when processing each
619 /// request, it is used to limit the number of actively running threads.
620 static ASTWorkerHandle
621 create(PathRef FileName
, const GlobalCompilationDatabase
&CDB
,
622 TUScheduler::ASTCache
&IdleASTs
,
623 TUScheduler::HeaderIncluderCache
&HeaderIncluders
,
624 AsyncTaskRunner
*Tasks
, Semaphore
&Barrier
,
625 const TUScheduler::Options
&Opts
, ParsingCallbacks
&Callbacks
);
627 ASTWorker(const ASTWorker
&other
) = delete;
628 ASTWorker
&operator=(const ASTWorker
&other
) = delete;
629 void update(ParseInputs Inputs
, WantDiagnostics
, bool ContentChanged
);
631 runWithAST(llvm::StringRef Name
,
632 llvm::unique_function
<void(llvm::Expected
<InputsAndAST
>)> Action
,
633 TUScheduler::ASTActionInvalidation
);
634 bool blockUntilIdle(Deadline Timeout
) const;
636 std::shared_ptr
<const PreambleData
> getPossiblyStalePreamble(
637 std::shared_ptr
<const ASTSignals
> *ASTSignals
= nullptr) const;
639 /// Used to inform ASTWorker about a new preamble build by PreambleThread.
640 /// Diagnostics are only published through this callback. This ensures they
641 /// are always for newer versions of the file, as the callback gets called in
642 /// the same order as update requests.
643 void updatePreamble(std::unique_ptr
<CompilerInvocation
> CI
, ParseInputs PI
,
644 std::shared_ptr
<const PreambleData
> Preamble
,
645 std::vector
<Diag
> CIDiags
, WantDiagnostics WantDiags
);
647 /// Returns compile command from the current file inputs.
648 tooling::CompileCommand
getCurrentCompileCommand() const;
650 /// Wait for the first build of preamble to finish. Preamble itself can be
651 /// accessed via getPossiblyStalePreamble(). Note that this function will
652 /// return after an unsuccessful build of the preamble too, i.e. result of
653 /// getPossiblyStalePreamble() can be null even after this function returns.
654 void waitForFirstPreamble() const;
656 TUScheduler::FileStats
stats() const;
657 bool isASTCached() const;
660 // Details of an update request that are relevant to scheduling.
662 // Do we want diagnostics from this version?
663 // If Yes, we must always build this version.
664 // If No, we only need to build this version if it's read.
665 // If Auto, we build if it's read or if the debounce expires.
666 WantDiagnostics Diagnostics
;
667 // Did the main-file content of the document change?
668 // If so, we're allowed to cancel certain invalidated preceding reads.
672 /// Publishes diagnostics for \p Inputs. It will build an AST or reuse the
673 /// cached one if applicable. Assumes LatestPreamble is compatible for \p
675 void generateDiagnostics(std::unique_ptr
<CompilerInvocation
> Invocation
,
676 ParseInputs Inputs
, std::vector
<Diag
> CIDiags
);
678 void updateASTSignals(ParsedAST
&AST
);
680 // Must be called exactly once on processing thread. Will return after
681 // stop() is called on a separate thread and all pending requests are
684 /// Signal that run() should finish processing pending requests and exit.
687 /// Adds a new task to the end of the request queue.
688 void startTask(llvm::StringRef Name
, llvm::unique_function
<void()> Task
,
689 std::optional
<UpdateType
> Update
,
690 TUScheduler::ASTActionInvalidation
);
691 /// Runs a task synchronously.
692 void runTask(llvm::StringRef Name
, llvm::function_ref
<void()> Task
);
694 /// Determines the next action to perform.
695 /// All actions that should never run are discarded.
696 /// Returns a deadline for the next action. If it's expired, run now.
697 /// scheduleLocked() is called again at the deadline, or if requests arrive.
698 Deadline
scheduleLocked();
699 /// Should the first task in the queue be skipped instead of run?
700 bool shouldSkipHeadLocked() const;
703 llvm::unique_function
<void()> Action
;
705 steady_clock::time_point AddTime
;
707 std::optional
<Context
> QueueCtx
;
708 std::optional
<UpdateType
> Update
;
709 TUScheduler::ASTActionInvalidation InvalidationPolicy
;
713 /// Handles retention of ASTs.
714 TUScheduler::ASTCache
&IdleASTs
;
715 TUScheduler::HeaderIncluderCache
&HeaderIncluders
;
717 /// Time to wait after an update to see whether another update obsoletes it.
718 const DebouncePolicy UpdateDebounce
;
719 /// File that ASTWorker is responsible for.
721 /// Callback to create processing contexts for tasks.
722 const std::function
<Context(llvm::StringRef
)> ContextProvider
;
723 const GlobalCompilationDatabase
&CDB
;
724 /// Callback invoked when preamble or main file AST is built.
725 ParsingCallbacks
&Callbacks
;
728 /// Whether the 'onMainAST' callback ran for the current FileInputs.
729 bool RanASTCallback
= false;
730 /// Guards members used by both TUScheduler and the worker thread.
731 mutable std::mutex Mutex
;
732 /// File inputs, currently being used by the worker.
733 /// Writes and reads from unknown threads are locked. Reads from the worker
734 /// thread are not locked, as it's the only writer.
735 ParseInputs FileInputs
; /* GUARDED_BY(Mutex) */
736 /// Times of recent AST rebuilds, used for UpdateDebounce computation.
737 llvm::SmallVector
<DebouncePolicy::clock::duration
>
738 RebuildTimes
; /* GUARDED_BY(Mutex) */
739 /// Set to true to signal run() to finish processing.
740 bool Done
; /* GUARDED_BY(Mutex) */
741 std::deque
<Request
> Requests
; /* GUARDED_BY(Mutex) */
742 std::optional
<Request
> CurrentRequest
; /* GUARDED_BY(Mutex) */
743 /// Signalled whenever a new request has been scheduled or processing of a
744 /// request has completed.
745 mutable std::condition_variable RequestsCV
;
746 std::shared_ptr
<const ASTSignals
> LatestASTSignals
; /* GUARDED_BY(Mutex) */
747 /// Latest build preamble for current TU.
748 /// std::nullopt means no builds yet, null means there was an error while
749 /// building. Only written by ASTWorker's thread.
750 std::optional
<std::shared_ptr
<const PreambleData
>> LatestPreamble
;
751 std::deque
<Request
> PreambleRequests
; /* GUARDED_BY(Mutex) */
752 /// Signaled whenever LatestPreamble changes state or there's a new
754 mutable std::condition_variable PreambleCV
;
755 /// Guards the callback that publishes results of AST-related computations
756 /// (diagnostics) and file statuses.
757 std::mutex PublishMu
;
758 // Used to prevent remove document + add document races that lead to
759 // out-of-order callbacks for publishing results of onMainAST callback.
761 // The lifetime of the old/new ASTWorkers will overlap, but their handles
762 // don't. When the old handle is destroyed, the old worker will stop reporting
763 // any results to the user.
764 bool CanPublishResults
= true; /* GUARDED_BY(PublishMu) */
765 std::atomic
<unsigned> ASTBuildCount
= {0};
766 std::atomic
<unsigned> PreambleBuildCount
= {0};
768 SynchronizedTUStatus Status
;
769 PreambleThread PreamblePeer
;
772 /// A smart-pointer-like class that points to an active ASTWorker.
773 /// In destructor, signals to the underlying ASTWorker that no new requests will
774 /// be sent and the processing loop may exit (after running all pending
776 class ASTWorkerHandle
{
777 friend class ASTWorker
;
778 ASTWorkerHandle(std::shared_ptr
<ASTWorker
> Worker
)
779 : Worker(std::move(Worker
)) {
780 assert(this->Worker
);
784 ASTWorkerHandle(const ASTWorkerHandle
&) = delete;
785 ASTWorkerHandle
&operator=(const ASTWorkerHandle
&) = delete;
786 ASTWorkerHandle(ASTWorkerHandle
&&) = default;
787 ASTWorkerHandle
&operator=(ASTWorkerHandle
&&) = default;
794 ASTWorker
&operator*() {
795 assert(Worker
&& "Handle was moved from");
799 ASTWorker
*operator->() {
800 assert(Worker
&& "Handle was moved from");
804 /// Returns an owning reference to the underlying ASTWorker that can outlive
805 /// the ASTWorkerHandle. However, no new requests to an active ASTWorker can
806 /// be schedule via the returned reference, i.e. only reads of the preamble
808 std::shared_ptr
<const ASTWorker
> lock() { return Worker
; }
811 std::shared_ptr
<ASTWorker
> Worker
;
815 ASTWorker::create(PathRef FileName
, const GlobalCompilationDatabase
&CDB
,
816 TUScheduler::ASTCache
&IdleASTs
,
817 TUScheduler::HeaderIncluderCache
&HeaderIncluders
,
818 AsyncTaskRunner
*Tasks
, Semaphore
&Barrier
,
819 const TUScheduler::Options
&Opts
,
820 ParsingCallbacks
&Callbacks
) {
821 std::shared_ptr
<ASTWorker
> Worker(
822 new ASTWorker(FileName
, CDB
, IdleASTs
, HeaderIncluders
, Barrier
,
823 /*RunSync=*/!Tasks
, Opts
, Callbacks
));
825 Tasks
->runAsync("ASTWorker:" + llvm::sys::path::filename(FileName
),
826 [Worker
]() { Worker
->run(); });
827 Tasks
->runAsync("PreambleWorker:" + llvm::sys::path::filename(FileName
),
828 [Worker
]() { Worker
->PreamblePeer
.run(); });
831 return ASTWorkerHandle(std::move(Worker
));
834 ASTWorker::ASTWorker(PathRef FileName
, const GlobalCompilationDatabase
&CDB
,
835 TUScheduler::ASTCache
&LRUCache
,
836 TUScheduler::HeaderIncluderCache
&HeaderIncluders
,
837 Semaphore
&Barrier
, bool RunSync
,
838 const TUScheduler::Options
&Opts
,
839 ParsingCallbacks
&Callbacks
)
840 : IdleASTs(LRUCache
), HeaderIncluders(HeaderIncluders
), RunSync(RunSync
),
841 UpdateDebounce(Opts
.UpdateDebounce
), FileName(FileName
),
842 ContextProvider(Opts
.ContextProvider
), CDB(CDB
), Callbacks(Callbacks
),
843 Barrier(Barrier
), Done(false), Status(FileName
, Callbacks
),
844 PreamblePeer(FileName
, Callbacks
, Opts
.StorePreamblesInMemory
, RunSync
,
845 Opts
.PreambleThrottler
, Status
, HeaderIncluders
, *this) {
846 // Set a fallback command because compile command can be accessed before
847 // `Inputs` is initialized. Other fields are only used after initialization
848 // from client inputs.
849 FileInputs
.CompileCommand
= CDB
.getFallbackCommand(FileName
);
852 ASTWorker::~ASTWorker() {
853 // Make sure we remove the cached AST, if any.
856 std::lock_guard
<std::mutex
> Lock(Mutex
);
857 assert(Done
&& "handle was not destroyed");
858 assert(Requests
.empty() && !CurrentRequest
&&
859 "unprocessed requests when destroying ASTWorker");
863 void ASTWorker::update(ParseInputs Inputs
, WantDiagnostics WantDiags
,
864 bool ContentChanged
) {
865 llvm::StringLiteral TaskName
= "Update";
866 auto Task
= [=]() mutable {
867 // Get the actual command as `Inputs` does not have a command.
868 // FIXME: some build systems like Bazel will take time to preparing
869 // environment to build the file, it would be nice if we could emit a
870 // "PreparingBuild" status to inform users, it is non-trivial given the
871 // current implementation.
872 auto Cmd
= CDB
.getCompileCommand(FileName
);
873 // If we don't have a reliable command for this file, it may be a header.
874 // Try to find a file that includes it, to borrow its command.
875 if (!Cmd
|| !isReliable(*Cmd
)) {
876 std::string ProxyFile
= HeaderIncluders
.get(FileName
);
877 if (!ProxyFile
.empty()) {
878 auto ProxyCmd
= CDB
.getCompileCommand(ProxyFile
);
879 if (!ProxyCmd
|| !isReliable(*ProxyCmd
)) {
880 // This command is supposed to be reliable! It's probably gone.
881 HeaderIncluders
.remove(ProxyFile
);
883 // We have a reliable command for an including file, use it.
884 Cmd
= tooling::transferCompileCommand(std::move(*ProxyCmd
), FileName
);
889 Inputs
.CompileCommand
= std::move(*Cmd
);
891 Inputs
.CompileCommand
= CDB
.getFallbackCommand(FileName
);
893 bool InputsAreTheSame
=
894 std::tie(FileInputs
.CompileCommand
, FileInputs
.Contents
) ==
895 std::tie(Inputs
.CompileCommand
, Inputs
.Contents
);
896 // Cached AST is invalidated.
897 if (!InputsAreTheSame
) {
899 RanASTCallback
= false;
902 // Update current inputs so that subsequent reads can see them.
904 std::lock_guard
<std::mutex
> Lock(Mutex
);
908 log("ASTWorker building file {0} version {1} with command {2}\n[{3}]\n{4}",
909 FileName
, Inputs
.Version
, Inputs
.CompileCommand
.Heuristic
,
910 Inputs
.CompileCommand
.Directory
,
911 printArgv(Inputs
.CompileCommand
.CommandLine
));
913 StoreDiags CompilerInvocationDiagConsumer
;
914 std::vector
<std::string
> CC1Args
;
915 std::unique_ptr
<CompilerInvocation
> Invocation
= buildCompilerInvocation(
916 Inputs
, CompilerInvocationDiagConsumer
, &CC1Args
);
917 // Log cc1 args even (especially!) if creating invocation failed.
918 if (!CC1Args
.empty())
919 vlog("Driver produced command: cc1 {0}", printArgv(CC1Args
));
920 std::vector
<Diag
> CompilerInvocationDiags
=
921 CompilerInvocationDiagConsumer
.take();
923 elog("Could not build CompilerInvocation for file {0}", FileName
);
924 // Remove the old AST if it's still in cache.
926 RanASTCallback
= false;
927 // Report the diagnostics we collected when parsing the command line.
928 Callbacks
.onFailedAST(FileName
, Inputs
.Version
,
929 std::move(CompilerInvocationDiags
),
930 [&](llvm::function_ref
<void()> Publish
) {
931 // Ensure we only publish results from the worker
932 // if the file was not removed, making sure there
933 // are not race conditions.
934 std::lock_guard
<std::mutex
> Lock(PublishMu
);
935 if (CanPublishResults
)
938 // Note that this might throw away a stale preamble that might still be
939 // useful, but this is how we communicate a build error.
940 LatestPreamble
.emplace();
941 // Make sure anyone waiting for the preamble gets notified it could not be
943 PreambleCV
.notify_all();
947 // Inform preamble peer, before attempting to build diagnostics so that they
948 // can be built concurrently.
949 PreamblePeer
.update(std::make_unique
<CompilerInvocation
>(*Invocation
),
950 Inputs
, CompilerInvocationDiags
, WantDiags
);
952 // Emit diagnostics from (possibly) stale preamble while waiting for a
953 // rebuild. Newly built preamble cannot emit diagnostics before this call
954 // finishes (ast callbacks are called from astpeer thread), hence we
955 // guarantee eventual consistency.
956 if (LatestPreamble
&& WantDiags
!= WantDiagnostics::No
)
957 generateDiagnostics(std::move(Invocation
), std::move(Inputs
),
958 std::move(CompilerInvocationDiags
));
960 std::unique_lock
<std::mutex
> Lock(Mutex
);
961 PreambleCV
.wait(Lock
, [this] {
962 // Block until we reiceve a preamble request, unless a preamble already
963 // exists, as patching an empty preamble would imply rebuilding it from
965 // We block here instead of the consumer to prevent any deadlocks. Since
966 // LatestPreamble is only populated by ASTWorker thread.
967 return LatestPreamble
|| !PreambleRequests
.empty() || Done
;
970 startTask(TaskName
, std::move(Task
), UpdateType
{WantDiags
, ContentChanged
},
971 TUScheduler::NoInvalidation
);
974 void ASTWorker::runWithAST(
975 llvm::StringRef Name
,
976 llvm::unique_function
<void(llvm::Expected
<InputsAndAST
>)> Action
,
977 TUScheduler::ASTActionInvalidation Invalidation
) {
978 // Tracks ast cache accesses for read operations.
979 static constexpr trace::Metric
ASTAccessForRead(
980 "ast_access_read", trace::Metric::Counter
, "result");
981 auto Task
= [=, Action
= std::move(Action
)]() mutable {
982 if (auto Reason
= isCancelled())
983 return Action(llvm::make_error
<CancelledError
>(Reason
));
984 std::optional
<std::unique_ptr
<ParsedAST
>> AST
=
985 IdleASTs
.take(this, &ASTAccessForRead
);
987 StoreDiags CompilerInvocationDiagConsumer
;
988 std::unique_ptr
<CompilerInvocation
> Invocation
=
989 buildCompilerInvocation(FileInputs
, CompilerInvocationDiagConsumer
);
990 // Try rebuilding the AST.
991 vlog("ASTWorker rebuilding evicted AST to run {0}: {1} version {2}", Name
,
992 FileName
, FileInputs
.Version
);
993 // FIXME: We might need to build a patched ast once preamble thread starts
994 // running async. Currently getPossiblyStalePreamble below will always
995 // return a compatible preamble as ASTWorker::update blocks.
996 std::optional
<ParsedAST
> NewAST
;
998 NewAST
= ParsedAST::build(FileName
, FileInputs
, std::move(Invocation
),
999 CompilerInvocationDiagConsumer
.take(),
1000 getPossiblyStalePreamble());
1003 AST
= NewAST
? std::make_unique
<ParsedAST
>(std::move(*NewAST
)) : nullptr;
1005 // Make sure we put the AST back into the LRU cache.
1006 auto _
= llvm::make_scope_exit(
1007 [&AST
, this]() { IdleASTs
.put(this, std::move(*AST
)); });
1008 // Run the user-provided action.
1010 return Action(error(llvm::errc::invalid_argument
, "invalid AST"));
1011 vlog("ASTWorker running {0} on version {2} of {1}", Name
, FileName
,
1012 FileInputs
.Version
);
1013 Action(InputsAndAST
{FileInputs
, **AST
});
1015 startTask(Name
, std::move(Task
), /*Update=*/std::nullopt
, Invalidation
);
1018 /// To be called from ThreadCrashReporter's signal handler.
1019 static void crashDumpCompileCommand(llvm::raw_ostream
&OS
,
1020 const tooling::CompileCommand
&Command
) {
1021 OS
<< " Filename: " << Command
.Filename
<< "\n";
1022 OS
<< " Directory: " << Command
.Directory
<< "\n";
1023 OS
<< " Command Line:";
1024 for (auto &Arg
: Command
.CommandLine
) {
1030 /// To be called from ThreadCrashReporter's signal handler.
1031 static void crashDumpFileContents(llvm::raw_ostream
&OS
,
1032 const std::string
&Contents
) {
1033 // Avoid flooding the terminal with source code by default, but allow clients
1034 // to opt in. Use an env var to preserve backwards compatibility of the
1035 // command line interface, while allowing it to be set outside the clangd
1036 // launch site for more flexibility.
1037 if (getenv("CLANGD_CRASH_DUMP_SOURCE")) {
1038 OS
<< " Contents:\n";
1039 OS
<< Contents
<< "\n";
1043 /// To be called from ThreadCrashReporter's signal handler.
1044 static void crashDumpParseInputs(llvm::raw_ostream
&OS
,
1045 const ParseInputs
&FileInputs
) {
1046 auto &Command
= FileInputs
.CompileCommand
;
1047 crashDumpCompileCommand(OS
, Command
);
1048 OS
<< " Version: " << FileInputs
.Version
<< "\n";
1049 crashDumpFileContents(OS
, FileInputs
.Contents
);
1052 void PreambleThread::build(Request Req
) {
1053 assert(Req
.CI
&& "Got preamble request with null compiler invocation");
1054 const ParseInputs
&Inputs
= Req
.Inputs
;
1055 bool ReusedPreamble
= false;
1057 Status
.update([&](TUStatus
&Status
) {
1058 Status
.PreambleActivity
= PreambleAction::Building
;
1060 auto _
= llvm::make_scope_exit([this, &Req
, &ReusedPreamble
] {
1061 ASTPeer
.updatePreamble(std::move(Req
.CI
), std::move(Req
.Inputs
),
1062 LatestBuild
, std::move(Req
.CIDiags
),
1063 std::move(Req
.WantDiags
));
1064 if (!ReusedPreamble
)
1065 Callbacks
.onPreamblePublished(FileName
);
1068 if (!LatestBuild
|| Inputs
.ForceRebuild
) {
1069 vlog("Building first preamble for {0} version {1}", FileName
,
1071 } else if (isPreambleCompatible(*LatestBuild
, Inputs
, FileName
, *Req
.CI
)) {
1072 vlog("Reusing preamble version {0} for version {1} of {2}",
1073 LatestBuild
->Version
, Inputs
.Version
, FileName
);
1074 ReusedPreamble
= true;
1077 vlog("Rebuilding invalidated preamble for {0} version {1} (previous was "
1079 FileName
, Inputs
.Version
, LatestBuild
->Version
);
1082 ThreadCrashReporter
ScopedReporter([&Inputs
]() {
1083 llvm::errs() << "Signalled while building preamble\n";
1084 crashDumpParseInputs(llvm::errs(), Inputs
);
1087 PreambleBuildStats Stats
;
1088 bool IsFirstPreamble
= !LatestBuild
;
1089 LatestBuild
= clang::clangd::buildPreamble(
1090 FileName
, *Req
.CI
, Inputs
, StoreInMemory
,
1091 [&](CapturedASTCtx ASTCtx
,
1092 std::shared_ptr
<const include_cleaner::PragmaIncludes
> PI
) {
1093 Callbacks
.onPreambleAST(FileName
, Inputs
.Version
, std::move(ASTCtx
),
1099 reportPreambleBuild(Stats
, IsFirstPreamble
);
1100 if (isReliable(LatestBuild
->CompileCommand
))
1101 HeaderIncluders
.update(FileName
, LatestBuild
->Includes
.allHeaders());
1104 void ASTWorker::updatePreamble(std::unique_ptr
<CompilerInvocation
> CI
,
1106 std::shared_ptr
<const PreambleData
> Preamble
,
1107 std::vector
<Diag
> CIDiags
,
1108 WantDiagnostics WantDiags
) {
1109 llvm::StringLiteral TaskName
= "Build AST";
1110 // Store preamble and build diagnostics with new preamble if requested.
1111 auto Task
= [this, Preamble
= std::move(Preamble
), CI
= std::move(CI
),
1112 CIDiags
= std::move(CIDiags
),
1113 WantDiags
= std::move(WantDiags
)]() mutable {
1114 // Update the preamble inside ASTWorker queue to ensure atomicity. As a task
1115 // running inside ASTWorker assumes internals won't change until it
1117 if (!LatestPreamble
|| Preamble
!= *LatestPreamble
) {
1118 ++PreambleBuildCount
;
1119 // Cached AST is no longer valid.
1120 IdleASTs
.take(this);
1121 RanASTCallback
= false;
1122 std::lock_guard
<std::mutex
> Lock(Mutex
);
1123 // LatestPreamble might be the last reference to old preamble, do not
1124 // trigger destructor while holding the lock.
1126 std::swap(*LatestPreamble
, Preamble
);
1128 LatestPreamble
= std::move(Preamble
);
1130 // Notify anyone waiting for a preamble.
1131 PreambleCV
.notify_all();
1132 // Give up our ownership to old preamble before starting expensive AST
1135 // We only need to build the AST if diagnostics were requested.
1136 if (WantDiags
== WantDiagnostics::No
)
1138 // Since the file may have been edited since we started building this
1139 // preamble, we use the current contents of the file instead. This provides
1140 // more up-to-date diagnostics, and avoids diagnostics going backwards (we
1141 // may have already emitted staler-preamble diagnostics for the new
1143 // We still have eventual consistency: at some point updatePreamble() will
1144 // catch up to the current file.
1145 // Report diagnostics with the new preamble to ensure progress. Otherwise
1146 // diagnostics might get stale indefinitely if user keeps invalidating the
1148 generateDiagnostics(std::move(CI
), FileInputs
, std::move(CIDiags
));
1151 runTask(TaskName
, Task
);
1155 std::lock_guard
<std::mutex
> Lock(Mutex
);
1156 PreambleRequests
.push_back({std::move(Task
), std::string(TaskName
),
1157 steady_clock::now(), Context::current().clone(),
1158 std::nullopt
, std::nullopt
,
1159 TUScheduler::NoInvalidation
, nullptr});
1161 PreambleCV
.notify_all();
1162 RequestsCV
.notify_all();
1165 void ASTWorker::updateASTSignals(ParsedAST
&AST
) {
1166 auto Signals
= std::make_shared
<const ASTSignals
>(ASTSignals::derive(AST
));
1167 // Existing readers of ASTSignals will have their copy preserved until the
1168 // read is completed. The last reader deletes the old ASTSignals.
1170 std::lock_guard
<std::mutex
> Lock(Mutex
);
1171 std::swap(LatestASTSignals
, Signals
);
1175 void ASTWorker::generateDiagnostics(
1176 std::unique_ptr
<CompilerInvocation
> Invocation
, ParseInputs Inputs
,
1177 std::vector
<Diag
> CIDiags
) {
1178 // Tracks ast cache accesses for publishing diags.
1179 static constexpr trace::Metric
ASTAccessForDiag(
1180 "ast_access_diag", trace::Metric::Counter
, "result");
1182 assert(LatestPreamble
);
1183 // No need to rebuild the AST if we won't send the diagnostics.
1185 std::lock_guard
<std::mutex
> Lock(PublishMu
);
1186 if (!CanPublishResults
)
1189 // Used to check whether we can update AST cache.
1190 bool InputsAreLatest
=
1191 std::tie(FileInputs
.CompileCommand
, FileInputs
.Contents
) ==
1192 std::tie(Inputs
.CompileCommand
, Inputs
.Contents
);
1193 // Take a shortcut and don't report the diagnostics, since they should be the
1194 // same. All the clients should handle the lack of OnUpdated() call anyway to
1195 // handle empty result from buildAST.
1196 // FIXME: the AST could actually change if non-preamble includes changed,
1197 // but we choose to ignore it.
1198 if (InputsAreLatest
&& RanASTCallback
)
1201 // Get the AST for diagnostics, either build it or use the cached one.
1202 std::string TaskName
= llvm::formatv("Build AST ({0})", Inputs
.Version
);
1203 Status
.update([&](TUStatus
&Status
) {
1204 Status
.ASTActivity
.K
= ASTAction::Building
;
1205 Status
.ASTActivity
.Name
= std::move(TaskName
);
1207 // We might be able to reuse the last we've built for a read request.
1208 // FIXME: It might be better to not reuse this AST. That way queued AST builds
1209 // won't be required for diags.
1210 std::optional
<std::unique_ptr
<ParsedAST
>> AST
=
1211 IdleASTs
.take(this, &ASTAccessForDiag
);
1212 if (!AST
|| !InputsAreLatest
) {
1213 auto RebuildStartTime
= DebouncePolicy::clock::now();
1214 std::optional
<ParsedAST
> NewAST
= ParsedAST::build(
1215 FileName
, Inputs
, std::move(Invocation
), CIDiags
, *LatestPreamble
);
1216 auto RebuildDuration
= DebouncePolicy::clock::now() - RebuildStartTime
;
1218 // Try to record the AST-build time, to inform future update debouncing.
1219 // This is best-effort only: if the lock is held, don't bother.
1220 std::unique_lock
<std::mutex
> Lock(Mutex
, std::try_to_lock
);
1221 if (Lock
.owns_lock()) {
1222 // Do not let RebuildTimes grow beyond its small-size (i.e.
1224 if (RebuildTimes
.size() == RebuildTimes
.capacity())
1225 RebuildTimes
.erase(RebuildTimes
.begin());
1226 RebuildTimes
.push_back(RebuildDuration
);
1229 Status
.update([&](TUStatus
&Status
) {
1230 Status
.Details
.ReuseAST
= false;
1231 Status
.Details
.BuildFailed
= !NewAST
;
1233 AST
= NewAST
? std::make_unique
<ParsedAST
>(std::move(*NewAST
)) : nullptr;
1235 log("Skipping rebuild of the AST for {0}, inputs are the same.", FileName
);
1236 Status
.update([](TUStatus
&Status
) {
1237 Status
.Details
.ReuseAST
= true;
1238 Status
.Details
.BuildFailed
= false;
1242 // Publish diagnostics.
1243 auto RunPublish
= [&](llvm::function_ref
<void()> Publish
) {
1244 // Ensure we only publish results from the worker if the file was not
1245 // removed, making sure there are not race conditions.
1246 std::lock_guard
<std::mutex
> Lock(PublishMu
);
1247 if (CanPublishResults
)
1251 trace::Span
Span("Running main AST callback");
1252 Callbacks
.onMainAST(FileName
, **AST
, RunPublish
);
1253 updateASTSignals(**AST
);
1255 // Failed to build the AST, at least report diagnostics from the
1256 // command line if there were any.
1257 // FIXME: we might have got more errors while trying to build the
1258 // AST, surface them too.
1259 Callbacks
.onFailedAST(FileName
, Inputs
.Version
, CIDiags
, RunPublish
);
1262 // AST might've been built for an older version of the source, as ASTWorker
1263 // queue raced ahead while we were waiting on the preamble. In that case the
1264 // queue can't reuse the AST.
1265 if (InputsAreLatest
) {
1266 RanASTCallback
= *AST
!= nullptr;
1267 IdleASTs
.put(this, std::move(*AST
));
1271 std::shared_ptr
<const PreambleData
> ASTWorker::getPossiblyStalePreamble(
1272 std::shared_ptr
<const ASTSignals
> *ASTSignals
) const {
1273 std::lock_guard
<std::mutex
> Lock(Mutex
);
1275 *ASTSignals
= LatestASTSignals
;
1276 return LatestPreamble
? *LatestPreamble
: nullptr;
1279 void ASTWorker::waitForFirstPreamble() const {
1280 std::unique_lock
<std::mutex
> Lock(Mutex
);
1281 PreambleCV
.wait(Lock
, [this] { return LatestPreamble
|| Done
; });
1284 tooling::CompileCommand
ASTWorker::getCurrentCompileCommand() const {
1285 std::unique_lock
<std::mutex
> Lock(Mutex
);
1286 return FileInputs
.CompileCommand
;
1289 TUScheduler::FileStats
ASTWorker::stats() const {
1290 TUScheduler::FileStats Result
;
1291 Result
.ASTBuilds
= ASTBuildCount
;
1292 Result
.PreambleBuilds
= PreambleBuildCount
;
1293 // Note that we don't report the size of ASTs currently used for processing
1294 // the in-flight requests. We used this information for debugging purposes
1295 // only, so this should be fine.
1296 Result
.UsedBytesAST
= IdleASTs
.getUsedBytes(this);
1297 if (auto Preamble
= getPossiblyStalePreamble())
1298 Result
.UsedBytesPreamble
= Preamble
->Preamble
.getSize();
1302 bool ASTWorker::isASTCached() const { return IdleASTs
.getUsedBytes(this) != 0; }
1304 void ASTWorker::stop() {
1306 std::lock_guard
<std::mutex
> Lock(PublishMu
);
1307 CanPublishResults
= false;
1310 std::lock_guard
<std::mutex
> Lock(Mutex
);
1311 assert(!Done
&& "stop() called twice");
1314 PreamblePeer
.stop();
1315 // We are no longer going to build any preambles, let the waiters know that.
1316 PreambleCV
.notify_all();
1318 RequestsCV
.notify_all();
1321 void ASTWorker::runTask(llvm::StringRef Name
, llvm::function_ref
<void()> Task
) {
1322 ThreadCrashReporter
ScopedReporter([this, Name
]() {
1323 llvm::errs() << "Signalled during AST worker action: " << Name
<< "\n";
1324 crashDumpParseInputs(llvm::errs(), FileInputs
);
1326 trace::Span
Tracer(Name
);
1327 WithContext
WithProvidedContext(ContextProvider(FileName
));
1331 void ASTWorker::startTask(llvm::StringRef Name
,
1332 llvm::unique_function
<void()> Task
,
1333 std::optional
<UpdateType
> Update
,
1334 TUScheduler::ASTActionInvalidation Invalidation
) {
1336 assert(!Done
&& "running a task after stop()");
1337 runTask(Name
, Task
);
1342 std::lock_guard
<std::mutex
> Lock(Mutex
);
1343 assert(!Done
&& "running a task after stop()");
1344 // Cancel any requests invalidated by this request.
1345 if (Update
&& Update
->ContentChanged
) {
1346 for (auto &R
: llvm::reverse(Requests
)) {
1347 if (R
.InvalidationPolicy
== TUScheduler::InvalidateOnUpdate
)
1349 if (R
.Update
&& R
.Update
->ContentChanged
)
1350 break; // Older requests were already invalidated by the older update.
1354 // Allow this request to be cancelled if invalidated.
1355 Context Ctx
= Context::current().derive(FileBeingProcessed
, FileName
);
1356 Canceler Invalidate
= nullptr;
1358 WithContext
WC(std::move(Ctx
));
1359 std::tie(Ctx
, Invalidate
) = cancelableTask(
1360 /*Reason=*/static_cast<int>(ErrorCode::ContentModified
));
1362 // Trace the time the request spends in the queue, and the requests that
1363 // it's going to wait for.
1364 std::optional
<Context
> QueueCtx
;
1365 if (trace::enabled()) {
1366 // Tracers that follow threads and need strict nesting will see a tiny
1367 // instantaneous event "we're enqueueing", and sometime later it runs.
1368 WithContext
WC(Ctx
.clone());
1369 trace::Span
Tracer("Queued:" + Name
);
1372 SPAN_ATTACH(Tracer
, "CurrentRequest", CurrentRequest
->Name
);
1373 llvm::json::Array PreambleRequestsNames
;
1374 for (const auto &Req
: PreambleRequests
)
1375 PreambleRequestsNames
.push_back(Req
.Name
);
1376 SPAN_ATTACH(Tracer
, "PreambleRequestsNames",
1377 std::move(PreambleRequestsNames
));
1378 llvm::json::Array RequestsNames
;
1379 for (const auto &Req
: Requests
)
1380 RequestsNames
.push_back(Req
.Name
);
1381 SPAN_ATTACH(Tracer
, "RequestsNames", std::move(RequestsNames
));
1383 // For tracers that follow contexts, keep the trace span's context alive
1384 // until we dequeue the request, so they see the full duration.
1385 QueueCtx
= Context::current().clone();
1387 Requests
.push_back({std::move(Task
), std::string(Name
), steady_clock::now(),
1388 std::move(Ctx
), std::move(QueueCtx
), Update
,
1389 Invalidation
, std::move(Invalidate
)});
1391 RequestsCV
.notify_all();
1394 void ASTWorker::run() {
1395 clang::noteBottomOfStack();
1398 std::unique_lock
<std::mutex
> Lock(Mutex
);
1399 assert(!CurrentRequest
&& "A task is already running, multiple workers?");
1400 for (auto Wait
= scheduleLocked(); !Wait
.expired();
1401 Wait
= scheduleLocked()) {
1402 assert(PreambleRequests
.empty() &&
1403 "Preamble updates should be scheduled immediately");
1405 if (Requests
.empty())
1407 // Even though Done is set, finish pending requests.
1408 break; // However, skip delays to shutdown fast.
1411 // Tracing: we have a next request, attribute this sleep to it.
1412 std::optional
<WithContext
> Ctx
;
1413 std::optional
<trace::Span
> Tracer
;
1414 if (!Requests
.empty()) {
1415 Ctx
.emplace(Requests
.front().Ctx
.clone());
1416 Tracer
.emplace("Debounce");
1417 SPAN_ATTACH(*Tracer
, "next_request", Requests
.front().Name
);
1418 if (!(Wait
== Deadline::infinity())) {
1419 Status
.update([&](TUStatus
&Status
) {
1420 Status
.ASTActivity
.K
= ASTAction::Queued
;
1421 Status
.ASTActivity
.Name
= Requests
.front().Name
;
1423 SPAN_ATTACH(*Tracer
, "sleep_ms",
1424 std::chrono::duration_cast
<std::chrono::milliseconds
>(
1425 Wait
.time() - steady_clock::now())
1430 wait(Lock
, RequestsCV
, Wait
);
1432 // Any request in ReceivedPreambles is at least as old as the
1433 // Requests.front(), so prefer them first to preserve LSP order.
1434 if (!PreambleRequests
.empty()) {
1435 CurrentRequest
= std::move(PreambleRequests
.front());
1436 PreambleRequests
.pop_front();
1438 CurrentRequest
= std::move(Requests
.front());
1439 Requests
.pop_front();
1443 // Inform tracing that the request was dequeued.
1444 CurrentRequest
->QueueCtx
.reset();
1446 // It is safe to perform reads to CurrentRequest without holding the lock as
1447 // only writer is also this thread.
1449 std::unique_lock
<Semaphore
> Lock(Barrier
, std::try_to_lock
);
1450 if (!Lock
.owns_lock()) {
1451 Status
.update([&](TUStatus
&Status
) {
1452 Status
.ASTActivity
.K
= ASTAction::Queued
;
1453 Status
.ASTActivity
.Name
= CurrentRequest
->Name
;
1457 WithContext
Guard(std::move(CurrentRequest
->Ctx
));
1458 Status
.update([&](TUStatus
&Status
) {
1459 Status
.ASTActivity
.K
= ASTAction::RunningAction
;
1460 Status
.ASTActivity
.Name
= CurrentRequest
->Name
;
1462 runTask(CurrentRequest
->Name
, CurrentRequest
->Action
);
1465 bool IsEmpty
= false;
1467 std::lock_guard
<std::mutex
> Lock(Mutex
);
1468 CurrentRequest
.reset();
1469 IsEmpty
= Requests
.empty() && PreambleRequests
.empty();
1472 Status
.update([&](TUStatus
&Status
) {
1473 Status
.ASTActivity
.K
= ASTAction::Idle
;
1474 Status
.ASTActivity
.Name
= "";
1477 RequestsCV
.notify_all();
1481 Deadline
ASTWorker::scheduleLocked() {
1482 // Process new preambles immediately.
1483 if (!PreambleRequests
.empty())
1484 return Deadline::zero();
1485 if (Requests
.empty())
1486 return Deadline::infinity(); // Wait for new requests.
1487 // Handle cancelled requests first so the rest of the scheduler doesn't.
1488 for (auto I
= Requests
.begin(), E
= Requests
.end(); I
!= E
; ++I
) {
1489 if (!isCancelled(I
->Ctx
)) {
1490 // Cancellations after the first read don't affect current scheduling.
1491 if (I
->Update
== std::nullopt
)
1495 // Cancelled reads are moved to the front of the queue and run immediately.
1496 if (I
->Update
== std::nullopt
) {
1497 Request R
= std::move(*I
);
1499 Requests
.push_front(std::move(R
));
1500 return Deadline::zero();
1502 // Cancelled updates are downgraded to auto-diagnostics, and may be elided.
1503 if (I
->Update
->Diagnostics
== WantDiagnostics::Yes
)
1504 I
->Update
->Diagnostics
= WantDiagnostics::Auto
;
1507 while (shouldSkipHeadLocked()) {
1508 vlog("ASTWorker skipping {0} for {1}", Requests
.front().Name
, FileName
);
1509 Requests
.pop_front();
1511 assert(!Requests
.empty() && "skipped the whole queue");
1512 // Some updates aren't dead yet, but never end up being used.
1513 // e.g. the first keystroke is live until obsoleted by the second.
1514 // We debounce "maybe-unused" writes, sleeping in case they become dead.
1515 // But don't delay reads (including updates where diagnostics are needed).
1516 for (const auto &R
: Requests
)
1517 if (R
.Update
== std::nullopt
||
1518 R
.Update
->Diagnostics
== WantDiagnostics::Yes
)
1519 return Deadline::zero();
1520 // Front request needs to be debounced, so determine when we're ready.
1521 Deadline
D(Requests
.front().AddTime
+ UpdateDebounce
.compute(RebuildTimes
));
1525 // Returns true if Requests.front() is a dead update that can be skipped.
1526 bool ASTWorker::shouldSkipHeadLocked() const {
1527 assert(!Requests
.empty());
1528 auto Next
= Requests
.begin();
1529 auto Update
= Next
->Update
;
1530 if (!Update
) // Only skip updates.
1533 // An update is live if its AST might still be read.
1534 // That is, if it's not immediately followed by another update.
1535 if (Next
== Requests
.end() || !Next
->Update
)
1537 // The other way an update can be live is if its diagnostics might be used.
1538 switch (Update
->Diagnostics
) {
1539 case WantDiagnostics::Yes
:
1540 return false; // Always used.
1541 case WantDiagnostics::No
:
1542 return true; // Always dead.
1543 case WantDiagnostics::Auto
:
1544 // Used unless followed by an update that generates diagnostics.
1545 for (; Next
!= Requests
.end(); ++Next
)
1546 if (Next
->Update
&& Next
->Update
->Diagnostics
!= WantDiagnostics::No
)
1547 return true; // Prefer later diagnostics.
1550 llvm_unreachable("Unknown WantDiagnostics");
1553 bool ASTWorker::blockUntilIdle(Deadline Timeout
) const {
1554 auto WaitUntilASTWorkerIsIdle
= [&] {
1555 std::unique_lock
<std::mutex
> Lock(Mutex
);
1556 return wait(Lock
, RequestsCV
, Timeout
, [&] {
1557 return PreambleRequests
.empty() && Requests
.empty() && !CurrentRequest
;
1560 // Make sure ASTWorker has processed all requests, which might issue new
1561 // updates to PreamblePeer.
1562 if (!WaitUntilASTWorkerIsIdle())
1564 // Now that ASTWorker processed all requests, ensure PreamblePeer has served
1565 // all update requests. This might create new PreambleRequests for the
1567 if (!PreamblePeer
.blockUntilIdle(Timeout
))
1569 assert(Requests
.empty() &&
1570 "No new normal tasks can be scheduled concurrently with "
1571 "blockUntilIdle(): ASTWorker isn't threadsafe");
1572 // Finally make sure ASTWorker has processed all of the preamble updates.
1573 return WaitUntilASTWorkerIsIdle();
1576 // Render a TUAction to a user-facing string representation.
1577 // TUAction represents clangd-internal states, we don't intend to expose them
1578 // to users (say C++ programmers) directly to avoid confusion, we use terms that
1579 // are familiar by C++ programmers.
1580 std::string
renderTUAction(const PreambleAction PA
, const ASTAction
&AA
) {
1581 llvm::SmallVector
<std::string
, 2> Result
;
1583 case PreambleAction::Building
:
1584 Result
.push_back("parsing includes");
1586 case PreambleAction::Queued
:
1587 Result
.push_back("includes are queued");
1589 case PreambleAction::Idle
:
1590 // We handle idle specially below.
1594 case ASTAction::Queued
:
1595 Result
.push_back("file is queued");
1597 case ASTAction::RunningAction
:
1598 Result
.push_back("running " + AA
.Name
);
1600 case ASTAction::Building
:
1601 Result
.push_back("parsing main file");
1603 case ASTAction::Idle
:
1604 // We handle idle specially below.
1609 return llvm::join(Result
, ", ");
1614 unsigned getDefaultAsyncThreadsCount() {
1615 return llvm::heavyweight_hardware_concurrency().compute_thread_count();
1618 FileStatus
TUStatus::render(PathRef File
) const {
1620 FStatus
.uri
= URIForFile::canonicalize(File
, /*TUPath=*/File
);
1621 FStatus
.state
= renderTUAction(PreambleActivity
, ASTActivity
);
1625 struct TUScheduler::FileData
{
1626 /// Latest inputs, passed to TUScheduler::update().
1627 std::string Contents
;
1628 ASTWorkerHandle Worker
;
1631 TUScheduler::TUScheduler(const GlobalCompilationDatabase
&CDB
,
1632 const Options
&Opts
,
1633 std::unique_ptr
<ParsingCallbacks
> Callbacks
)
1634 : CDB(CDB
), Opts(Opts
),
1635 Callbacks(Callbacks
? std::move(Callbacks
)
1636 : std::make_unique
<ParsingCallbacks
>()),
1637 Barrier(Opts
.AsyncThreadsCount
), QuickRunBarrier(Opts
.AsyncThreadsCount
),
1639 std::make_unique
<ASTCache
>(Opts
.RetentionPolicy
.MaxRetainedASTs
)),
1640 HeaderIncluders(std::make_unique
<HeaderIncluderCache
>()) {
1641 // Avoid null checks everywhere.
1642 if (!Opts
.ContextProvider
) {
1643 this->Opts
.ContextProvider
= [](llvm::StringRef
) {
1644 return Context::current().clone();
1647 if (0 < Opts
.AsyncThreadsCount
) {
1648 PreambleTasks
.emplace();
1649 WorkerThreads
.emplace();
1653 TUScheduler::~TUScheduler() {
1654 // Notify all workers that they need to stop.
1657 // Wait for all in-flight tasks to finish.
1659 PreambleTasks
->wait();
1661 WorkerThreads
->wait();
1664 bool TUScheduler::blockUntilIdle(Deadline D
) const {
1665 for (auto &File
: Files
)
1666 if (!File
.getValue()->Worker
->blockUntilIdle(D
))
1669 if (!PreambleTasks
->wait(D
))
1674 bool TUScheduler::update(PathRef File
, ParseInputs Inputs
,
1675 WantDiagnostics WantDiags
) {
1676 std::unique_ptr
<FileData
> &FD
= Files
[File
];
1677 bool NewFile
= FD
== nullptr;
1678 bool ContentChanged
= false;
1680 // Create a new worker to process the AST-related tasks.
1681 ASTWorkerHandle Worker
= ASTWorker::create(
1682 File
, CDB
, *IdleASTs
, *HeaderIncluders
,
1683 WorkerThreads
? &*WorkerThreads
: nullptr, Barrier
, Opts
, *Callbacks
);
1684 FD
= std::unique_ptr
<FileData
>(
1685 new FileData
{Inputs
.Contents
, std::move(Worker
)});
1686 ContentChanged
= true;
1687 } else if (FD
->Contents
!= Inputs
.Contents
) {
1688 ContentChanged
= true;
1689 FD
->Contents
= Inputs
.Contents
;
1691 FD
->Worker
->update(std::move(Inputs
), WantDiags
, ContentChanged
);
1692 // There might be synthetic update requests, don't change the LastActiveFile
1695 LastActiveFile
= File
.str();
1699 void TUScheduler::remove(PathRef File
) {
1700 bool Removed
= Files
.erase(File
);
1702 elog("Trying to remove file from TUScheduler that is not tracked: {0}",
1704 // We don't call HeaderIncluders.remove(File) here.
1705 // If we did, we'd avoid potentially stale header/mainfile associations.
1706 // However, it would mean that closing a mainfile could invalidate the
1707 // preamble of several open headers.
1710 void TUScheduler::run(llvm::StringRef Name
, llvm::StringRef Path
,
1711 llvm::unique_function
<void()> Action
) {
1712 runWithSemaphore(Name
, Path
, std::move(Action
), Barrier
);
1715 void TUScheduler::runQuick(llvm::StringRef Name
, llvm::StringRef Path
,
1716 llvm::unique_function
<void()> Action
) {
1717 // Use QuickRunBarrier to serialize quick tasks: we are ignoring
1718 // the parallelism level set by the user, don't abuse it
1719 runWithSemaphore(Name
, Path
, std::move(Action
), QuickRunBarrier
);
1722 void TUScheduler::runWithSemaphore(llvm::StringRef Name
, llvm::StringRef Path
,
1723 llvm::unique_function
<void()> Action
,
1726 Path
= LastActiveFile
;
1728 LastActiveFile
= Path
.str();
1729 if (!PreambleTasks
) {
1730 WithContext
WithProvidedContext(Opts
.ContextProvider(Path
));
1733 PreambleTasks
->runAsync(Name
, [this, &Sem
, Ctx
= Context::current().clone(),
1735 Action
= std::move(Action
)]() mutable {
1736 std::lock_guard
<Semaphore
> BarrierLock(Sem
);
1737 WithContext
WC(std::move(Ctx
));
1738 WithContext
WithProvidedContext(Opts
.ContextProvider(Path
));
1743 void TUScheduler::runWithAST(
1744 llvm::StringRef Name
, PathRef File
,
1745 llvm::unique_function
<void(llvm::Expected
<InputsAndAST
>)> Action
,
1746 TUScheduler::ASTActionInvalidation Invalidation
) {
1747 auto It
= Files
.find(File
);
1748 if (It
== Files
.end()) {
1749 Action(llvm::make_error
<LSPError
>(
1750 "trying to get AST for non-added document", ErrorCode::InvalidParams
));
1753 LastActiveFile
= File
.str();
1755 It
->second
->Worker
->runWithAST(Name
, std::move(Action
), Invalidation
);
1758 void TUScheduler::runWithPreamble(llvm::StringRef Name
, PathRef File
,
1759 PreambleConsistency Consistency
,
1760 Callback
<InputsAndPreamble
> Action
) {
1761 auto It
= Files
.find(File
);
1762 if (It
== Files
.end()) {
1763 Action(llvm::make_error
<LSPError
>(
1764 "trying to get preamble for non-added document",
1765 ErrorCode::InvalidParams
));
1768 LastActiveFile
= File
.str();
1770 if (!PreambleTasks
) {
1771 trace::Span
Tracer(Name
);
1772 SPAN_ATTACH(Tracer
, "file", File
);
1773 std::shared_ptr
<const ASTSignals
> Signals
;
1774 std::shared_ptr
<const PreambleData
> Preamble
=
1775 It
->second
->Worker
->getPossiblyStalePreamble(&Signals
);
1776 WithContext
WithProvidedContext(Opts
.ContextProvider(File
));
1777 Action(InputsAndPreamble
{It
->second
->Contents
,
1778 It
->second
->Worker
->getCurrentCompileCommand(),
1779 Preamble
.get(), Signals
.get()});
1783 std::shared_ptr
<const ASTWorker
> Worker
= It
->second
->Worker
.lock();
1784 auto Task
= [Worker
, Consistency
, Name
= Name
.str(), File
= File
.str(),
1785 Contents
= It
->second
->Contents
,
1786 Command
= Worker
->getCurrentCompileCommand(),
1787 Ctx
= Context::current().derive(FileBeingProcessed
,
1789 Action
= std::move(Action
), this]() mutable {
1790 clang::noteBottomOfStack();
1791 ThreadCrashReporter
ScopedReporter([&Name
, &Contents
, &Command
]() {
1792 llvm::errs() << "Signalled during preamble action: " << Name
<< "\n";
1793 crashDumpCompileCommand(llvm::errs(), Command
);
1794 crashDumpFileContents(llvm::errs(), Contents
);
1796 std::shared_ptr
<const PreambleData
> Preamble
;
1797 if (Consistency
== PreambleConsistency::Stale
) {
1798 // Wait until the preamble is built for the first time, if preamble
1799 // is required. This avoids extra work of processing the preamble
1800 // headers in parallel multiple times.
1801 Worker
->waitForFirstPreamble();
1803 std::shared_ptr
<const ASTSignals
> Signals
;
1804 Preamble
= Worker
->getPossiblyStalePreamble(&Signals
);
1806 std::lock_guard
<Semaphore
> BarrierLock(Barrier
);
1807 WithContext
Guard(std::move(Ctx
));
1808 trace::Span
Tracer(Name
);
1809 SPAN_ATTACH(Tracer
, "file", File
);
1810 WithContext
WithProvidedContext(Opts
.ContextProvider(File
));
1811 Action(InputsAndPreamble
{Contents
, Command
, Preamble
.get(), Signals
.get()});
1814 PreambleTasks
->runAsync("task:" + llvm::sys::path::filename(File
),
1818 llvm::StringMap
<TUScheduler::FileStats
> TUScheduler::fileStats() const {
1819 llvm::StringMap
<TUScheduler::FileStats
> Result
;
1820 for (const auto &PathAndFile
: Files
)
1821 Result
.try_emplace(PathAndFile
.first(),
1822 PathAndFile
.second
->Worker
->stats());
1826 std::vector
<Path
> TUScheduler::getFilesWithCachedAST() const {
1827 std::vector
<Path
> Result
;
1828 for (auto &&PathAndFile
: Files
) {
1829 if (!PathAndFile
.second
->Worker
->isASTCached())
1831 Result
.push_back(std::string(PathAndFile
.first()));
1836 DebouncePolicy::clock::duration
1837 DebouncePolicy::compute(llvm::ArrayRef
<clock::duration
> History
) const {
1838 assert(Min
<= Max
&& "Invalid policy");
1839 if (History
.empty())
1840 return Max
; // Arbitrary.
1842 // Base the result on the median rebuild.
1843 // nth_element needs a mutable array, take the chance to bound the data size.
1844 History
= History
.take_back(15);
1845 llvm::SmallVector
<clock::duration
, 15> Recent(History
);
1846 auto *Median
= Recent
.begin() + Recent
.size() / 2;
1847 std::nth_element(Recent
.begin(), Median
, Recent
.end());
1849 clock::duration Target
=
1850 std::chrono::duration_cast
<clock::duration
>(RebuildRatio
* *Median
);
1858 DebouncePolicy
DebouncePolicy::fixed(clock::duration T
) {
1864 void TUScheduler::profile(MemoryTree
&MT
) const {
1865 for (const auto &Elem
: fileStats()) {
1866 MT
.detail(Elem
.first())
1868 .addUsage(Opts
.StorePreamblesInMemory
? Elem
.second
.UsedBytesPreamble
1870 MT
.detail(Elem
.first()).child("ast").addUsage(Elem
.second
.UsedBytesAST
);
1871 MT
.child("header_includer_cache").addUsage(HeaderIncluders
->getUsedBytes());
1874 } // namespace clangd
1875 } // namespace clang