xref: /third_party/node/deps/v8/src/logging/metrics.h (revision 1cb0ef41)
1// Copyright 2020 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef V8_LOGGING_METRICS_H_
6#define V8_LOGGING_METRICS_H_
7
8#include <memory>
9#include <queue>
10
11#include "include/v8-metrics.h"
12#include "src/base/platform/mutex.h"
13#include "src/base/platform/time.h"
14#include "src/init/v8.h"
15
16namespace v8 {
17
18class TaskRunner;
19
20namespace internal {
21namespace metrics {
22
23class Recorder : public std::enable_shared_from_this<Recorder> {
24 public:
25  V8_EXPORT_PRIVATE void SetEmbedderRecorder(
26      Isolate* isolate,
27      const std::shared_ptr<v8::metrics::Recorder>& embedder_recorder);
28
29  V8_EXPORT_PRIVATE bool HasEmbedderRecorder() const;
30
31  V8_EXPORT_PRIVATE void NotifyIsolateDisposal();
32
33  template <class T>
34  void AddMainThreadEvent(const T& event,
35                          v8::metrics::Recorder::ContextId id) {
36    if (embedder_recorder_)
37      embedder_recorder_->AddMainThreadEvent(event, id);
38  }
39
40  template <class T>
41  void DelayMainThreadEvent(const T& event,
42                            v8::metrics::Recorder::ContextId id) {
43    if (!embedder_recorder_) return;
44    Delay(std::make_unique<DelayedEvent<T>>(event, id));
45  }
46
47  template <class T>
48  void AddThreadSafeEvent(const T& event) {
49    if (embedder_recorder_) embedder_recorder_->AddThreadSafeEvent(event);
50  }
51
52 private:
53  class DelayedEventBase {
54   public:
55    virtual ~DelayedEventBase() = default;
56
57    virtual void Run(const std::shared_ptr<Recorder>& recorder) = 0;
58  };
59
60  template <class T>
61  class DelayedEvent : public DelayedEventBase {
62   public:
63    DelayedEvent(const T& event, v8::metrics::Recorder::ContextId id)
64        : event_(event), id_(id) {}
65
66    void Run(const std::shared_ptr<Recorder>& recorder) override {
67      recorder->AddMainThreadEvent(event_, id_);
68    }
69
70   protected:
71    T event_;
72    v8::metrics::Recorder::ContextId id_;
73  };
74
75  class Task;
76
77  V8_EXPORT_PRIVATE void Delay(
78      std::unique_ptr<Recorder::DelayedEventBase>&& event);
79
80  base::Mutex lock_;
81  std::shared_ptr<v8::TaskRunner> foreground_task_runner_;
82  std::shared_ptr<v8::metrics::Recorder> embedder_recorder_;
83  std::queue<std::unique_ptr<DelayedEventBase>> delayed_events_;
84};
85
86template <class T, int64_t (base::TimeDelta::*precision)() const =
87                       &base::TimeDelta::InMicroseconds>
88class V8_NODISCARD TimedScope {
89 public:
90  explicit TimedScope(T* event) : event_(event) { Start(); }
91  ~TimedScope() { Stop(); }
92
93  void Start() { start_time_ = base::TimeTicks::Now(); }
94
95  void Stop() {
96    if (start_time_.IsMin()) return;
97    base::TimeDelta duration = base::TimeTicks::Now() - start_time_;
98    event_->wall_clock_duration_in_us = (duration.*precision)();
99    start_time_ = base::TimeTicks::Min();
100  }
101
102 private:
103  T* event_;
104  base::TimeTicks start_time_;
105};
106
107}  // namespace metrics
108}  // namespace internal
109}  // namespace v8
110
111#endif  // V8_LOGGING_METRICS_H_
112