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 16namespace v8 { 17 18class TaskRunner; 19 20namespace internal { 21namespace metrics { 22 23class 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> 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> 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> 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: 63 DelayedEvent(const T& event, v8::metrics::Recorder::ContextId id) 64 : event_(event), id_(id) {} 65 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 86template <class T, int64_t (base::TimeDelta::*precision)() const = 87 &base::TimeDelta::InMicroseconds> 88class V8_NODISCARD TimedScope { 89 public: 90 explicit TimedScope(T* event) : event_(event) { Start(); } 91 ~TimedScope() { Stop(); } 92 93 void Start() { start_time_ = base::TimeTicks::Now(); } 94 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