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