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