metrics.h 2.84 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_LOGGING_METRICS_H_
#define V8_LOGGING_METRICS_H_

#include <memory>
#include <queue>

#include "include/v8-metrics.h"
#include "src/base/platform/mutex.h"
#include "src/base/platform/time.h"
#include "src/init/v8.h"

namespace v8 {

class TaskRunner;

namespace internal {
namespace metrics {

class Recorder : public std::enable_shared_from_this<Recorder> {
 public:
  V8_EXPORT_PRIVATE void SetRecorder(
26
      Isolate* isolate,
27 28 29 30 31
      const std::shared_ptr<v8::metrics::Recorder>& embedder_recorder);

  V8_EXPORT_PRIVATE void NotifyIsolateDisposal();

  template <class T>
32 33
  void AddMainThreadEvent(const T& event,
                          v8::metrics::Recorder::ContextId id) {
34
    if (embedder_recorder_)
35
      embedder_recorder_->AddMainThreadEvent(event, id);
36 37 38
  }

  template <class T>
39 40
  void DelayMainThreadEvent(const T& event,
                            v8::metrics::Recorder::ContextId id) {
41
    if (!embedder_recorder_) return;
42
    Delay(std::make_unique<DelayedEvent<T>>(event, id));
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
  }

  template <class T>
  void AddThreadSafeEvent(const T& event) {
    if (embedder_recorder_) embedder_recorder_->AddThreadSafeEvent(event);
  }

 private:
  class DelayedEventBase {
   public:
    virtual ~DelayedEventBase() = default;

    virtual void Run(const std::shared_ptr<Recorder>& recorder) = 0;
  };

  template <class T>
  class DelayedEvent : public DelayedEventBase {
   public:
61 62
    DelayedEvent(const T& event, v8::metrics::Recorder::ContextId id)
        : event_(event), id_(id) {}
63 64

    void Run(const std::shared_ptr<Recorder>& recorder) override {
65
      recorder->AddMainThreadEvent(event_, id_);
66 67 68 69
    }

   protected:
    T event_;
70
    v8::metrics::Recorder::ContextId id_;
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
  };

  class Task;

  V8_EXPORT_PRIVATE void Delay(
      std::unique_ptr<Recorder::DelayedEventBase>&& event);

  base::Mutex lock_;
  std::shared_ptr<v8::TaskRunner> foreground_task_runner_;
  std::shared_ptr<v8::metrics::Recorder> embedder_recorder_;
  std::queue<std::unique_ptr<DelayedEventBase>> delayed_events_;
};

template <class T, int64_t (base::TimeDelta::*precision)() const =
                       &base::TimeDelta::InMicroseconds>
86
class V8_NODISCARD TimedScope {
87
 public:
88
  explicit TimedScope(T* event) : event_(event) { Start(); }
89 90 91 92 93 94
  ~TimedScope() { Stop(); }

  void Start() { start_time_ = base::TimeTicks::Now(); }

  void Stop() {
    if (start_time_.IsMin()) return;
95
    base::TimeDelta duration = base::TimeTicks::Now() - start_time_;
96
    event_->wall_clock_duration_in_us = (duration.*precision)();
97
    start_time_ = base::TimeTicks::Min();
98 99 100 101 102 103 104 105 106 107 108 109
  }

 private:
  T* event_;
  base::TimeTicks start_time_;
};

}  // namespace metrics
}  // namespace internal
}  // namespace v8

#endif  // V8_LOGGING_METRICS_H_