@@ -465,6 +465,7 @@ class ASTWorker {
465465 std::string Name;
466466 steady_clock::time_point AddTime;
467467 Context Ctx;
468+ llvm::Optional<Context> QueueCtx;
468469 llvm::Optional<UpdateType> Update;
469470 TUScheduler::ASTActionInvalidation InvalidationPolicy;
470471 Canceler Invalidate;
@@ -507,7 +508,7 @@ class ASTWorker {
507508 // / None means no builds yet, null means there was an error while building.
508509 // / Only written by ASTWorker's thread.
509510 llvm::Optional<std::shared_ptr<const PreambleData>> LatestPreamble;
510- std::queue <Request> PreambleRequests; /* GUARDED_BY(Mutex) */
511+ std::deque <Request> PreambleRequests; /* GUARDED_BY(Mutex) */
511512 // / Signaled whenever LatestPreamble changes state or there's a new
512513 // / PreambleRequest.
513514 mutable std::condition_variable PreambleCV;
@@ -826,9 +827,10 @@ void ASTWorker::updatePreamble(std::unique_ptr<CompilerInvocation> CI,
826827 }
827828 {
828829 std::lock_guard<std::mutex> Lock (Mutex);
829- PreambleRequests.push ({std::move (Task), std::move (TaskName),
830- steady_clock::now (), Context::current ().clone (),
831- llvm::None, TUScheduler::NoInvalidation, nullptr });
830+ PreambleRequests.push_back ({std::move (Task), std::move (TaskName),
831+ steady_clock::now (), Context::current ().clone (),
832+ llvm::None, llvm::None,
833+ TUScheduler::NoInvalidation, nullptr });
832834 }
833835 PreambleCV.notify_all ();
834836 RequestsCV.notify_all ();
@@ -1023,9 +1025,34 @@ void ASTWorker::startTask(llvm::StringRef Name,
10231025 std::tie (Ctx, Invalidate) = cancelableTask (
10241026 /* Reason=*/ static_cast <int >(ErrorCode::ContentModified));
10251027 }
1028+ // Trace the time the request spends in the queue, and the requests that
1029+ // it's going to wait for.
1030+ llvm::Optional<Context> QueueCtx;
1031+ if (trace::enabled ()) {
1032+ // Tracers that follow threads and need strict nesting will see a tiny
1033+ // instantaneous event "we're enqueueing", and sometime later it runs.
1034+ WithContext WC (Ctx.clone ());
1035+ trace::Span Tracer (" Queued:" + Name);
1036+ if (Tracer.Args ) {
1037+ if (CurrentRequest)
1038+ SPAN_ATTACH (Tracer, " CurrentRequest" , CurrentRequest->Name );
1039+ llvm::json::Array PreambleRequestsNames;
1040+ for (const auto &Req : PreambleRequests)
1041+ PreambleRequestsNames.push_back (Req.Name );
1042+ SPAN_ATTACH (Tracer, " PreambleRequestsNames" ,
1043+ std::move (PreambleRequestsNames));
1044+ llvm::json::Array RequestsNames;
1045+ for (const auto &Req : Requests)
1046+ RequestsNames.push_back (Req.Name );
1047+ SPAN_ATTACH (Tracer, " RequestsNames" , std::move (RequestsNames));
1048+ }
1049+ // For tracers that follow contexts, keep the trace span's context alive
1050+ // until we dequeue the request, so they see the full duration.
1051+ QueueCtx = Context::current ().clone ();
1052+ }
10261053 Requests.push_back ({std::move (Task), std::string (Name), steady_clock::now (),
1027- std::move (Ctx), Update, Invalidation ,
1028- std::move (Invalidate)});
1054+ std::move (Ctx), std::move (QueueCtx), Update ,
1055+ Invalidation, std::move (Invalidate)});
10291056 }
10301057 RequestsCV.notify_all ();
10311058}
@@ -1071,13 +1098,16 @@ void ASTWorker::run() {
10711098 // Requests.front(), so prefer them first to preserve LSP order.
10721099 if (!PreambleRequests.empty ()) {
10731100 CurrentRequest = std::move (PreambleRequests.front ());
1074- PreambleRequests.pop ();
1101+ PreambleRequests.pop_front ();
10751102 } else {
10761103 CurrentRequest = std::move (Requests.front ());
10771104 Requests.pop_front ();
10781105 }
10791106 } // unlock Mutex
10801107
1108+ // Inform tracing that the request was dequeued.
1109+ CurrentRequest->QueueCtx .reset ();
1110+
10811111 // It is safe to perform reads to CurrentRequest without holding the lock as
10821112 // only writer is also this thread.
10831113 {
0 commit comments