2017-11-02 17:21:51 +08:00
|
|
|
//===--- Trace.h - Performance tracing facilities ---------------*- C++ -*-===//
|
|
|
|
//
|
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
|
2017-11-02 17:21:51 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// Supports writing performance traces describing clangd's behavior.
|
2017-12-14 23:04:59 +08:00
|
|
|
// Traces are consumed by implementations of the EventTracer interface.
|
2017-11-02 17:21:51 +08:00
|
|
|
//
|
|
|
|
//
|
|
|
|
// All APIs are no-ops unless a Session is active (created by ClangdMain).
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_TRACE_H_
|
|
|
|
#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_TRACE_H_
|
|
|
|
|
2017-12-14 23:04:59 +08:00
|
|
|
#include "Context.h"
|
2017-12-14 23:33:38 +08:00
|
|
|
#include "Function.h"
|
2017-11-02 17:21:51 +08:00
|
|
|
#include "llvm/ADT/Twine.h"
|
2018-07-09 22:25:59 +08:00
|
|
|
#include "llvm/Support/JSON.h"
|
2017-11-02 17:21:51 +08:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
|
|
|
|
|
|
|
namespace clang {
|
|
|
|
namespace clangd {
|
|
|
|
namespace trace {
|
|
|
|
|
2017-12-14 23:04:59 +08:00
|
|
|
/// A consumer of trace events. The events are produced by Spans and trace::log.
|
2017-12-14 23:33:38 +08:00
|
|
|
/// Implmentations of this interface must be thread-safe.
|
2017-12-14 23:04:59 +08:00
|
|
|
class EventTracer {
|
|
|
|
public:
|
|
|
|
virtual ~EventTracer() = default;
|
2017-12-14 23:33:38 +08:00
|
|
|
|
2018-01-26 17:00:30 +08:00
|
|
|
/// Called when event that has a duration starts. \p Name describes the event.
|
|
|
|
/// Returns a derived context that will be destroyed when the event ends.
|
|
|
|
/// Usually implementations will store an object in the returned context
|
|
|
|
/// whose destructor records the end of the event.
|
|
|
|
/// The args are *Args, only complete when the event ends.
|
2018-07-09 22:25:59 +08:00
|
|
|
virtual Context beginSpan(llvm::StringRef Name, llvm::json::Object *Args) = 0;
|
2018-02-15 16:40:54 +08:00
|
|
|
// Called when a Span is destroyed (it may still be active on other threads).
|
|
|
|
// beginSpan() and endSpan() will always form a proper stack on each thread.
|
|
|
|
// The Context returned by beginSpan is active, but Args is not ready.
|
|
|
|
// Tracers should not override this unless they need to observe strict
|
|
|
|
// per-thread nesting. Instead they should observe context destruction.
|
2018-05-30 20:41:19 +08:00
|
|
|
virtual void endSpan(){};
|
2017-12-14 23:33:38 +08:00
|
|
|
|
|
|
|
/// Called for instant events.
|
2018-07-09 22:25:59 +08:00
|
|
|
virtual void instant(llvm::StringRef Name, llvm::json::Object &&Args) = 0;
|
2017-12-14 23:04:59 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
/// Sets up a global EventTracer that consumes events produced by Span and
|
|
|
|
/// trace::log. Only one TracingSession can be active at a time and it should be
|
|
|
|
/// set up before calling any clangd-specific functions.
|
2017-11-02 17:21:51 +08:00
|
|
|
class Session {
|
|
|
|
public:
|
2017-12-14 23:04:59 +08:00
|
|
|
Session(EventTracer &Tracer);
|
2017-11-02 17:21:51 +08:00
|
|
|
~Session();
|
|
|
|
};
|
|
|
|
|
2017-12-14 23:04:59 +08:00
|
|
|
/// Create an instance of EventTracer that produces an output in the Trace Event
|
|
|
|
/// format supported by Chrome's trace viewer (chrome://tracing).
|
|
|
|
///
|
|
|
|
/// The format is documented here:
|
|
|
|
/// https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/preview
|
|
|
|
std::unique_ptr<EventTracer> createJSONTracer(llvm::raw_ostream &OS,
|
|
|
|
bool Pretty = false);
|
2017-11-02 17:21:51 +08:00
|
|
|
|
2017-12-14 23:04:59 +08:00
|
|
|
/// Records a single instant event, associated with the current thread.
|
[clangd] Pass Context implicitly using TLS.
Summary:
Instead of passing Context explicitly around, we now have a thread-local
Context object `Context::current()` which is an implicit argument to
every function.
Most manipulation of this should use the WithContextValue helper, which
augments the current Context to add a single KV pair, and restores the
old context on destruction.
Advantages are:
- less boilerplate in functions that just propagate contexts
- reading most code doesn't require understanding context at all, and
using context as values in fewer places still
- fewer options to pass the "wrong" context when it changes within a
scope (e.g. when using Span)
- contexts pass through interfaces we can't modify, such as VFS
- propagating contexts across threads was slightly tricky (e.g.
copy vs move, no move-init in lambdas), and is now encapsulated in
the threadpool
Disadvantages are all the usual TLS stuff - hidden magic, and
potential for higher memory usage on threads that don't use the
context. (In practice, it's just one pointer)
Reviewers: ilya-biryukov
Subscribers: klimek, jkorous-apple, ioeric, cfe-commits
Differential Revision: https://reviews.llvm.org/D42517
llvm-svn: 323872
2018-01-31 21:40:48 +08:00
|
|
|
void log(const llvm::Twine &Name);
|
2017-12-14 23:04:59 +08:00
|
|
|
|
|
|
|
/// Records an event whose duration is the lifetime of the Span object.
|
2018-01-26 17:00:30 +08:00
|
|
|
/// This lifetime is extended when the span's context is reused.
|
|
|
|
///
|
2017-12-14 23:04:59 +08:00
|
|
|
/// This is the main public interface for producing tracing events.
|
|
|
|
///
|
|
|
|
/// Arbitrary JSON metadata can be attached while this span is active:
|
|
|
|
/// SPAN_ATTACH(MySpan, "Payload", SomeJSONExpr);
|
2018-01-26 17:00:30 +08:00
|
|
|
///
|
2017-12-14 23:04:59 +08:00
|
|
|
/// SomeJSONExpr is evaluated and copied only if actually needed.
|
2017-11-02 17:21:51 +08:00
|
|
|
class Span {
|
|
|
|
public:
|
2018-02-19 17:56:28 +08:00
|
|
|
Span(llvm::Twine Name);
|
2018-02-15 16:40:54 +08:00
|
|
|
~Span();
|
2017-11-02 17:21:51 +08:00
|
|
|
|
2018-01-26 17:00:30 +08:00
|
|
|
/// Mutable metadata, if this span is interested.
|
2017-12-14 23:04:59 +08:00
|
|
|
/// Prefer to use SPAN_ATTACH rather than accessing this directly.
|
[clangd] Ensure that we reply to each call exactly once. NFC (I think!)
Summary:
In debug builds, getting this wrong will trigger asserts.
In production builds, it will send an error reply if none was sent,
and drop redundant replies. (And log).
No tests because this is always a programming error.
(We did have some cases of this, but I fixed them with the new dispatcher).
Reviewers: ioeric
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, jfb, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53399
llvm-svn: 345144
2018-10-24 22:26:26 +08:00
|
|
|
/// The lifetime of Args is the whole event, even if the Span dies.
|
2018-07-09 22:25:59 +08:00
|
|
|
llvm::json::Object *const Args;
|
[clangd] Pass Context implicitly using TLS.
Summary:
Instead of passing Context explicitly around, we now have a thread-local
Context object `Context::current()` which is an implicit argument to
every function.
Most manipulation of this should use the WithContextValue helper, which
augments the current Context to add a single KV pair, and restores the
old context on destruction.
Advantages are:
- less boilerplate in functions that just propagate contexts
- reading most code doesn't require understanding context at all, and
using context as values in fewer places still
- fewer options to pass the "wrong" context when it changes within a
scope (e.g. when using Span)
- contexts pass through interfaces we can't modify, such as VFS
- propagating contexts across threads was slightly tricky (e.g.
copy vs move, no move-init in lambdas), and is now encapsulated in
the threadpool
Disadvantages are all the usual TLS stuff - hidden magic, and
potential for higher memory usage on threads that don't use the
context. (In practice, it's just one pointer)
Reviewers: ilya-biryukov
Subscribers: klimek, jkorous-apple, ioeric, cfe-commits
Differential Revision: https://reviews.llvm.org/D42517
llvm-svn: 323872
2018-01-31 21:40:48 +08:00
|
|
|
|
|
|
|
private:
|
|
|
|
WithContext RestoreCtx;
|
2017-11-02 17:21:51 +08:00
|
|
|
};
|
|
|
|
|
2018-01-26 17:00:30 +08:00
|
|
|
/// Attach a key-value pair to a Span event.
|
|
|
|
/// This is not threadsafe when used with the same Span.
|
2017-11-24 01:12:04 +08:00
|
|
|
#define SPAN_ATTACH(S, Name, Expr) \
|
|
|
|
do { \
|
2018-01-26 17:00:30 +08:00
|
|
|
if (auto *Args = (S).Args) \
|
|
|
|
(*Args)[Name] = Expr; \
|
2017-11-24 01:12:04 +08:00
|
|
|
} while (0)
|
|
|
|
|
2017-11-02 17:21:51 +08:00
|
|
|
} // namespace trace
|
|
|
|
} // namespace clangd
|
|
|
|
} // namespace clang
|
|
|
|
|
|
|
|
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_TRACE_H_
|