diff --git a/clang-tools-extra/clangd/TUScheduler.cpp b/clang-tools-extra/clangd/TUScheduler.cpp --- a/clang-tools-extra/clangd/TUScheduler.cpp +++ b/clang-tools-extra/clangd/TUScheduler.cpp @@ -143,10 +143,17 @@ /// the cache anymore. If nullptr was cached for \p K, this function will /// return a null unique_ptr wrapped into an optional. llvm::Optional> take(Key K) { + trace::Metric M("/clangd/ast_cache"); + M.Ty = trace::Metric::Increment; + M.Value = 1; + // Record metric after unlocking the mutex. std::unique_lock Lock(Mut); auto Existing = findByKey(K); - if (Existing == LRU.end()) + if (Existing == LRU.end()) { + M.Labels = {"miss"}; return None; + } + M.Labels = {"hit"}; std::unique_ptr V = std::move(Existing->second); LRU.erase(Existing); // GCC 4.8 fails to compile `return V;`, as it tries to call the copy diff --git a/clang-tools-extra/clangd/Trace.h b/clang-tools-extra/clangd/Trace.h --- a/clang-tools-extra/clangd/Trace.h +++ b/clang-tools-extra/clangd/Trace.h @@ -18,14 +18,40 @@ #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_TRACE_H_ #include "Context.h" +#include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/JSON.h" #include "llvm/Support/raw_ostream.h" +#include +#include namespace clang { namespace clangd { namespace trace { +/// Represents measurements of clangd events, e.g. operation latency. Reports +/// itself to active tracer on destruction. +struct Metric { + enum Type { + /// Occurence of an event, e.g. cache access. + Increment, + /// Aspect of an event, e.g. number of symbols in an index lookup. + Sample, + }; + /// Uniquely identifies the metric. + const llvm::StringLiteral Name; + /// Divides a metric into meaningful parts. e.g. hit/miss to represent result + /// of a cache access. + std::vector Labels; + double Value = 0; + Type Ty; + + Metric(llvm::StringLiteral Name) : Name(Name) {} + Metric(const Metric &) = delete; + Metric &operator=(const Metric &) = delete; + ~Metric(); +}; + /// A consumer of trace events. The events are produced by Spans and trace::log. /// Implementations of this interface must be thread-safe. class EventTracer { @@ -47,6 +73,9 @@ /// Called for instant events. virtual void instant(llvm::StringRef Name, llvm::json::Object &&Args) = 0; + + /// Called whenever an event exports a measurement. + virtual void record(const Metric &Metric) {} }; /// Sets up a global EventTracer that consumes events produced by Span and diff --git a/clang-tools-extra/clangd/Trace.cpp b/clang-tools-extra/clangd/Trace.cpp --- a/clang-tools-extra/clangd/Trace.cpp +++ b/clang-tools-extra/clangd/Trace.cpp @@ -149,10 +149,10 @@ void rawEvent(llvm::StringRef Phase, const llvm::json::Object &Event) /*REQUIRES(Mu)*/ { // PID 0 represents the clangd process. - Out.object([&]{ + Out.object([&] { Out.attribute("pid", 0); Out.attribute("ph", Phase); - for (const auto& KV : Event) + for (const auto &KV : Event) Out.attribute(KV.first, KV.second); }); } @@ -230,6 +230,12 @@ T->endSpan(); } +Metric::~Metric() { + if (!T) + return; + T->record(*this); +} + } // namespace trace } // namespace clangd } // namespace clang