• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
16 namespace v8 {
17 
18 class TaskRunner;
19 
20 namespace internal {
21 namespace metrics {
22 
23 class Recorder : public std::enable_shared_from_this<Recorder> {
24  public:
25   V8_EXPORT_PRIVATE void SetRecorder(
26       Isolate* isolate,
27       const std::shared_ptr<v8::metrics::Recorder>& embedder_recorder);
28 
29   V8_EXPORT_PRIVATE void NotifyIsolateDisposal();
30 
31   template <class T>
AddMainThreadEvent(const T & event,v8::metrics::Recorder::ContextId id)32   void AddMainThreadEvent(const T& event,
33                           v8::metrics::Recorder::ContextId id) {
34     if (embedder_recorder_)
35       embedder_recorder_->AddMainThreadEvent(event, id);
36   }
37 
38   template <class T>
DelayMainThreadEvent(const T & event,v8::metrics::Recorder::ContextId id)39   void DelayMainThreadEvent(const T& event,
40                             v8::metrics::Recorder::ContextId id) {
41     if (!embedder_recorder_) return;
42     Delay(std::make_unique<DelayedEvent<T>>(event, id));
43   }
44 
45   template <class T>
AddThreadSafeEvent(const T & event)46   void AddThreadSafeEvent(const T& event) {
47     if (embedder_recorder_) embedder_recorder_->AddThreadSafeEvent(event);
48   }
49 
50  private:
51   class DelayedEventBase {
52    public:
53     virtual ~DelayedEventBase() = default;
54 
55     virtual void Run(const std::shared_ptr<Recorder>& recorder) = 0;
56   };
57 
58   template <class T>
59   class DelayedEvent : public DelayedEventBase {
60    public:
DelayedEvent(const T & event,v8::metrics::Recorder::ContextId id)61     DelayedEvent(const T& event, v8::metrics::Recorder::ContextId id)
62         : event_(event), id_(id) {}
63 
Run(const std::shared_ptr<Recorder> & recorder)64     void Run(const std::shared_ptr<Recorder>& recorder) override {
65       recorder->AddMainThreadEvent(event_, id_);
66     }
67 
68    protected:
69     T event_;
70     v8::metrics::Recorder::ContextId id_;
71   };
72 
73   class Task;
74 
75   V8_EXPORT_PRIVATE void Delay(
76       std::unique_ptr<Recorder::DelayedEventBase>&& event);
77 
78   base::Mutex lock_;
79   std::shared_ptr<v8::TaskRunner> foreground_task_runner_;
80   std::shared_ptr<v8::metrics::Recorder> embedder_recorder_;
81   std::queue<std::unique_ptr<DelayedEventBase>> delayed_events_;
82 };
83 
84 template <class T, int64_t (base::TimeDelta::*precision)() const =
85                        &base::TimeDelta::InMicroseconds>
86 class TimedScope {
87  public:
TimedScope(T * event)88   explicit TimedScope(T* event) : event_(event) { Start(); }
~TimedScope()89   ~TimedScope() { Stop(); }
90 
Start()91   void Start() { start_time_ = base::TimeTicks::Now(); }
92 
Stop()93   void Stop() {
94     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  private:
101   T* event_;
102   base::TimeTicks start_time_;
103 };
104 
105 }  // namespace metrics
106 }  // namespace internal
107 }  // namespace v8
108 
109 #endif  // V8_LOGGING_METRICS_H_
110