• 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 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>
AddMainThreadEvent(const T & event,v8::metrics::Recorder::ContextId id)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>
DelayMainThreadEvent(const T & event,v8::metrics::Recorder::ContextId id)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>
AddThreadSafeEvent(const T & event)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:
DelayedEvent(const T & event,v8::metrics::Recorder::ContextId id)63     DelayedEvent(const T& event, v8::metrics::Recorder::ContextId id)
64         : event_(event), id_(id) {}
65 
Run(const std::shared_ptr<Recorder> & recorder)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 
86 template <class T, int64_t (base::TimeDelta::*precision)() const =
87                        &base::TimeDelta::InMicroseconds>
88 class V8_NODISCARD TimedScope {
89  public:
TimedScope(T * event)90   explicit TimedScope(T* event) : event_(event) { Start(); }
~TimedScope()91   ~TimedScope() { Stop(); }
92 
Start()93   void Start() { start_time_ = base::TimeTicks::Now(); }
94 
Stop()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