11cb0ef41Sopenharmony_ci// Copyright 2020 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#ifndef V8_METRICS_H_
61cb0ef41Sopenharmony_ci#define V8_METRICS_H_
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ci#include <stddef.h>
91cb0ef41Sopenharmony_ci#include <stdint.h>
101cb0ef41Sopenharmony_ci
111cb0ef41Sopenharmony_ci#include <vector>
121cb0ef41Sopenharmony_ci
131cb0ef41Sopenharmony_ci#include "v8-internal.h"      // NOLINT(build/include_directory)
141cb0ef41Sopenharmony_ci#include "v8-local-handle.h"  // NOLINT(build/include_directory)
151cb0ef41Sopenharmony_ci#include "v8config.h"         // NOLINT(build/include_directory)
161cb0ef41Sopenharmony_ci
171cb0ef41Sopenharmony_cinamespace v8 {
181cb0ef41Sopenharmony_ci
191cb0ef41Sopenharmony_ciclass Context;
201cb0ef41Sopenharmony_ciclass Isolate;
211cb0ef41Sopenharmony_ci
221cb0ef41Sopenharmony_cinamespace metrics {
231cb0ef41Sopenharmony_ci
241cb0ef41Sopenharmony_cistruct GarbageCollectionPhases {
251cb0ef41Sopenharmony_ci  int64_t total_wall_clock_duration_in_us = -1;
261cb0ef41Sopenharmony_ci  int64_t compact_wall_clock_duration_in_us = -1;
271cb0ef41Sopenharmony_ci  int64_t mark_wall_clock_duration_in_us = -1;
281cb0ef41Sopenharmony_ci  int64_t sweep_wall_clock_duration_in_us = -1;
291cb0ef41Sopenharmony_ci  int64_t weak_wall_clock_duration_in_us = -1;
301cb0ef41Sopenharmony_ci};
311cb0ef41Sopenharmony_ci
321cb0ef41Sopenharmony_cistruct GarbageCollectionSizes {
331cb0ef41Sopenharmony_ci  int64_t bytes_before = -1;
341cb0ef41Sopenharmony_ci  int64_t bytes_after = -1;
351cb0ef41Sopenharmony_ci  int64_t bytes_freed = -1;
361cb0ef41Sopenharmony_ci};
371cb0ef41Sopenharmony_ci
381cb0ef41Sopenharmony_cistruct GarbageCollectionFullCycle {
391cb0ef41Sopenharmony_ci  int reason = -1;
401cb0ef41Sopenharmony_ci  GarbageCollectionPhases total;
411cb0ef41Sopenharmony_ci  GarbageCollectionPhases total_cpp;
421cb0ef41Sopenharmony_ci  GarbageCollectionPhases main_thread;
431cb0ef41Sopenharmony_ci  GarbageCollectionPhases main_thread_cpp;
441cb0ef41Sopenharmony_ci  GarbageCollectionPhases main_thread_atomic;
451cb0ef41Sopenharmony_ci  GarbageCollectionPhases main_thread_atomic_cpp;
461cb0ef41Sopenharmony_ci  GarbageCollectionPhases main_thread_incremental;
471cb0ef41Sopenharmony_ci  GarbageCollectionPhases main_thread_incremental_cpp;
481cb0ef41Sopenharmony_ci  GarbageCollectionSizes objects;
491cb0ef41Sopenharmony_ci  GarbageCollectionSizes objects_cpp;
501cb0ef41Sopenharmony_ci  GarbageCollectionSizes memory;
511cb0ef41Sopenharmony_ci  GarbageCollectionSizes memory_cpp;
521cb0ef41Sopenharmony_ci  double collection_rate_in_percent = -1.0;
531cb0ef41Sopenharmony_ci  double collection_rate_cpp_in_percent = -1.0;
541cb0ef41Sopenharmony_ci  double efficiency_in_bytes_per_us = -1.0;
551cb0ef41Sopenharmony_ci  double efficiency_cpp_in_bytes_per_us = -1.0;
561cb0ef41Sopenharmony_ci  double main_thread_efficiency_in_bytes_per_us = -1.0;
571cb0ef41Sopenharmony_ci  double main_thread_efficiency_cpp_in_bytes_per_us = -1.0;
581cb0ef41Sopenharmony_ci};
591cb0ef41Sopenharmony_ci
601cb0ef41Sopenharmony_cistruct GarbageCollectionFullMainThreadIncrementalMark {
611cb0ef41Sopenharmony_ci  int64_t wall_clock_duration_in_us = -1;
621cb0ef41Sopenharmony_ci  int64_t cpp_wall_clock_duration_in_us = -1;
631cb0ef41Sopenharmony_ci};
641cb0ef41Sopenharmony_ci
651cb0ef41Sopenharmony_cistruct GarbageCollectionFullMainThreadIncrementalSweep {
661cb0ef41Sopenharmony_ci  int64_t wall_clock_duration_in_us = -1;
671cb0ef41Sopenharmony_ci  int64_t cpp_wall_clock_duration_in_us = -1;
681cb0ef41Sopenharmony_ci};
691cb0ef41Sopenharmony_ci
701cb0ef41Sopenharmony_citemplate <typename EventType>
711cb0ef41Sopenharmony_cistruct GarbageCollectionBatchedEvents {
721cb0ef41Sopenharmony_ci  std::vector<EventType> events;
731cb0ef41Sopenharmony_ci};
741cb0ef41Sopenharmony_ci
751cb0ef41Sopenharmony_ciusing GarbageCollectionFullMainThreadBatchedIncrementalMark =
761cb0ef41Sopenharmony_ci    GarbageCollectionBatchedEvents<
771cb0ef41Sopenharmony_ci        GarbageCollectionFullMainThreadIncrementalMark>;
781cb0ef41Sopenharmony_ciusing GarbageCollectionFullMainThreadBatchedIncrementalSweep =
791cb0ef41Sopenharmony_ci    GarbageCollectionBatchedEvents<
801cb0ef41Sopenharmony_ci        GarbageCollectionFullMainThreadIncrementalSweep>;
811cb0ef41Sopenharmony_ci
821cb0ef41Sopenharmony_cistruct GarbageCollectionYoungCycle {
831cb0ef41Sopenharmony_ci  int reason = -1;
841cb0ef41Sopenharmony_ci  int64_t total_wall_clock_duration_in_us = -1;
851cb0ef41Sopenharmony_ci  int64_t main_thread_wall_clock_duration_in_us = -1;
861cb0ef41Sopenharmony_ci  double collection_rate_in_percent = -1.0;
871cb0ef41Sopenharmony_ci  double efficiency_in_bytes_per_us = -1.0;
881cb0ef41Sopenharmony_ci  double main_thread_efficiency_in_bytes_per_us = -1.0;
891cb0ef41Sopenharmony_ci#if defined(CPPGC_YOUNG_GENERATION)
901cb0ef41Sopenharmony_ci  GarbageCollectionPhases total_cpp;
911cb0ef41Sopenharmony_ci  GarbageCollectionSizes objects_cpp;
921cb0ef41Sopenharmony_ci  GarbageCollectionSizes memory_cpp;
931cb0ef41Sopenharmony_ci  double collection_rate_cpp_in_percent = -1.0;
941cb0ef41Sopenharmony_ci  double efficiency_cpp_in_bytes_per_us = -1.0;
951cb0ef41Sopenharmony_ci  double main_thread_efficiency_cpp_in_bytes_per_us = -1.0;
961cb0ef41Sopenharmony_ci#endif  // defined(CPPGC_YOUNG_GENERATION)
971cb0ef41Sopenharmony_ci};
981cb0ef41Sopenharmony_ci
991cb0ef41Sopenharmony_cistruct WasmModuleDecoded {
1001cb0ef41Sopenharmony_ci  WasmModuleDecoded() = default;
1011cb0ef41Sopenharmony_ci  WasmModuleDecoded(bool async, bool streamed, bool success,
1021cb0ef41Sopenharmony_ci                    size_t module_size_in_bytes, size_t function_count,
1031cb0ef41Sopenharmony_ci                    int64_t wall_clock_duration_in_us)
1041cb0ef41Sopenharmony_ci      : async(async),
1051cb0ef41Sopenharmony_ci        streamed(streamed),
1061cb0ef41Sopenharmony_ci        success(success),
1071cb0ef41Sopenharmony_ci        module_size_in_bytes(module_size_in_bytes),
1081cb0ef41Sopenharmony_ci        function_count(function_count),
1091cb0ef41Sopenharmony_ci        wall_clock_duration_in_us(wall_clock_duration_in_us) {}
1101cb0ef41Sopenharmony_ci
1111cb0ef41Sopenharmony_ci  bool async = false;
1121cb0ef41Sopenharmony_ci  bool streamed = false;
1131cb0ef41Sopenharmony_ci  bool success = false;
1141cb0ef41Sopenharmony_ci  size_t module_size_in_bytes = 0;
1151cb0ef41Sopenharmony_ci  size_t function_count = 0;
1161cb0ef41Sopenharmony_ci  int64_t wall_clock_duration_in_us = -1;
1171cb0ef41Sopenharmony_ci};
1181cb0ef41Sopenharmony_ci
1191cb0ef41Sopenharmony_cistruct WasmModuleCompiled {
1201cb0ef41Sopenharmony_ci  WasmModuleCompiled() = default;
1211cb0ef41Sopenharmony_ci
1221cb0ef41Sopenharmony_ci  WasmModuleCompiled(bool async, bool streamed, bool cached, bool deserialized,
1231cb0ef41Sopenharmony_ci                     bool lazy, bool success, size_t code_size_in_bytes,
1241cb0ef41Sopenharmony_ci                     size_t liftoff_bailout_count,
1251cb0ef41Sopenharmony_ci                     int64_t wall_clock_duration_in_us)
1261cb0ef41Sopenharmony_ci      : async(async),
1271cb0ef41Sopenharmony_ci        streamed(streamed),
1281cb0ef41Sopenharmony_ci        cached(cached),
1291cb0ef41Sopenharmony_ci        deserialized(deserialized),
1301cb0ef41Sopenharmony_ci        lazy(lazy),
1311cb0ef41Sopenharmony_ci        success(success),
1321cb0ef41Sopenharmony_ci        code_size_in_bytes(code_size_in_bytes),
1331cb0ef41Sopenharmony_ci        liftoff_bailout_count(liftoff_bailout_count),
1341cb0ef41Sopenharmony_ci        wall_clock_duration_in_us(wall_clock_duration_in_us) {}
1351cb0ef41Sopenharmony_ci
1361cb0ef41Sopenharmony_ci  bool async = false;
1371cb0ef41Sopenharmony_ci  bool streamed = false;
1381cb0ef41Sopenharmony_ci  bool cached = false;
1391cb0ef41Sopenharmony_ci  bool deserialized = false;
1401cb0ef41Sopenharmony_ci  bool lazy = false;
1411cb0ef41Sopenharmony_ci  bool success = false;
1421cb0ef41Sopenharmony_ci  size_t code_size_in_bytes = 0;
1431cb0ef41Sopenharmony_ci  size_t liftoff_bailout_count = 0;
1441cb0ef41Sopenharmony_ci  int64_t wall_clock_duration_in_us = -1;
1451cb0ef41Sopenharmony_ci};
1461cb0ef41Sopenharmony_ci
1471cb0ef41Sopenharmony_cistruct WasmModuleInstantiated {
1481cb0ef41Sopenharmony_ci  bool async = false;
1491cb0ef41Sopenharmony_ci  bool success = false;
1501cb0ef41Sopenharmony_ci  size_t imported_function_count = 0;
1511cb0ef41Sopenharmony_ci  int64_t wall_clock_duration_in_us = -1;
1521cb0ef41Sopenharmony_ci};
1531cb0ef41Sopenharmony_ci
1541cb0ef41Sopenharmony_cistruct WasmModulesPerIsolate {
1551cb0ef41Sopenharmony_ci  size_t count = 0;
1561cb0ef41Sopenharmony_ci};
1571cb0ef41Sopenharmony_ci
1581cb0ef41Sopenharmony_ci/**
1591cb0ef41Sopenharmony_ci * This class serves as a base class for recording event-based metrics in V8.
1601cb0ef41Sopenharmony_ci * There a two kinds of metrics, those which are expected to be thread-safe and
1611cb0ef41Sopenharmony_ci * whose implementation is required to fulfill this requirement and those whose
1621cb0ef41Sopenharmony_ci * implementation does not have that requirement and only needs to be
1631cb0ef41Sopenharmony_ci * executable on the main thread. If such an event is triggered from a
1641cb0ef41Sopenharmony_ci * background thread, it will be delayed and executed by the foreground task
1651cb0ef41Sopenharmony_ci * runner.
1661cb0ef41Sopenharmony_ci *
1671cb0ef41Sopenharmony_ci * The embedder is expected to call v8::Isolate::SetMetricsRecorder()
1681cb0ef41Sopenharmony_ci * providing its implementation and have the virtual methods overwritten
1691cb0ef41Sopenharmony_ci * for the events it cares about.
1701cb0ef41Sopenharmony_ci */
1711cb0ef41Sopenharmony_ciclass V8_EXPORT Recorder {
1721cb0ef41Sopenharmony_ci public:
1731cb0ef41Sopenharmony_ci  // A unique identifier for a context in this Isolate.
1741cb0ef41Sopenharmony_ci  // It is guaranteed to not be reused throughout the lifetime of the Isolate.
1751cb0ef41Sopenharmony_ci  class ContextId {
1761cb0ef41Sopenharmony_ci   public:
1771cb0ef41Sopenharmony_ci    ContextId() : id_(kEmptyId) {}
1781cb0ef41Sopenharmony_ci
1791cb0ef41Sopenharmony_ci    bool IsEmpty() const { return id_ == kEmptyId; }
1801cb0ef41Sopenharmony_ci    static const ContextId Empty() { return ContextId{kEmptyId}; }
1811cb0ef41Sopenharmony_ci
1821cb0ef41Sopenharmony_ci    bool operator==(const ContextId& other) const { return id_ == other.id_; }
1831cb0ef41Sopenharmony_ci    bool operator!=(const ContextId& other) const { return id_ != other.id_; }
1841cb0ef41Sopenharmony_ci
1851cb0ef41Sopenharmony_ci   private:
1861cb0ef41Sopenharmony_ci    friend class ::v8::Context;
1871cb0ef41Sopenharmony_ci    friend class ::v8::internal::Isolate;
1881cb0ef41Sopenharmony_ci
1891cb0ef41Sopenharmony_ci    explicit ContextId(uintptr_t id) : id_(id) {}
1901cb0ef41Sopenharmony_ci
1911cb0ef41Sopenharmony_ci    static constexpr uintptr_t kEmptyId = 0;
1921cb0ef41Sopenharmony_ci    uintptr_t id_;
1931cb0ef41Sopenharmony_ci  };
1941cb0ef41Sopenharmony_ci
1951cb0ef41Sopenharmony_ci  virtual ~Recorder() = default;
1961cb0ef41Sopenharmony_ci
1971cb0ef41Sopenharmony_ci  // Main thread events. Those are only triggered on the main thread, and hence
1981cb0ef41Sopenharmony_ci  // can access the context.
1991cb0ef41Sopenharmony_ci#define ADD_MAIN_THREAD_EVENT(E) \
2001cb0ef41Sopenharmony_ci  virtual void AddMainThreadEvent(const E&, ContextId) {}
2011cb0ef41Sopenharmony_ci  ADD_MAIN_THREAD_EVENT(GarbageCollectionFullCycle)
2021cb0ef41Sopenharmony_ci  ADD_MAIN_THREAD_EVENT(GarbageCollectionFullMainThreadIncrementalMark)
2031cb0ef41Sopenharmony_ci  ADD_MAIN_THREAD_EVENT(GarbageCollectionFullMainThreadBatchedIncrementalMark)
2041cb0ef41Sopenharmony_ci  ADD_MAIN_THREAD_EVENT(GarbageCollectionFullMainThreadIncrementalSweep)
2051cb0ef41Sopenharmony_ci  ADD_MAIN_THREAD_EVENT(GarbageCollectionFullMainThreadBatchedIncrementalSweep)
2061cb0ef41Sopenharmony_ci  ADD_MAIN_THREAD_EVENT(GarbageCollectionYoungCycle)
2071cb0ef41Sopenharmony_ci  ADD_MAIN_THREAD_EVENT(WasmModuleDecoded)
2081cb0ef41Sopenharmony_ci  ADD_MAIN_THREAD_EVENT(WasmModuleCompiled)
2091cb0ef41Sopenharmony_ci  ADD_MAIN_THREAD_EVENT(WasmModuleInstantiated)
2101cb0ef41Sopenharmony_ci#undef ADD_MAIN_THREAD_EVENT
2111cb0ef41Sopenharmony_ci
2121cb0ef41Sopenharmony_ci  // Thread-safe events are not allowed to access the context and therefore do
2131cb0ef41Sopenharmony_ci  // not carry a context ID with them. These IDs can be generated using
2141cb0ef41Sopenharmony_ci  // Recorder::GetContextId() and the ID will be valid throughout the lifetime
2151cb0ef41Sopenharmony_ci  // of the isolate. It is not guaranteed that the ID will still resolve to
2161cb0ef41Sopenharmony_ci  // a valid context using Recorder::GetContext() at the time the metric is
2171cb0ef41Sopenharmony_ci  // recorded. In this case, an empty handle will be returned.
2181cb0ef41Sopenharmony_ci#define ADD_THREAD_SAFE_EVENT(E) \
2191cb0ef41Sopenharmony_ci  virtual void AddThreadSafeEvent(const E&) {}
2201cb0ef41Sopenharmony_ci  ADD_THREAD_SAFE_EVENT(WasmModulesPerIsolate)
2211cb0ef41Sopenharmony_ci#undef ADD_THREAD_SAFE_EVENT
2221cb0ef41Sopenharmony_ci
2231cb0ef41Sopenharmony_ci  virtual void NotifyIsolateDisposal() {}
2241cb0ef41Sopenharmony_ci
2251cb0ef41Sopenharmony_ci  // Return the context with the given id or an empty handle if the context
2261cb0ef41Sopenharmony_ci  // was already garbage collected.
2271cb0ef41Sopenharmony_ci  static MaybeLocal<Context> GetContext(Isolate* isolate, ContextId id);
2281cb0ef41Sopenharmony_ci  // Return the unique id corresponding to the given context.
2291cb0ef41Sopenharmony_ci  static ContextId GetContextId(Local<Context> context);
2301cb0ef41Sopenharmony_ci};
2311cb0ef41Sopenharmony_ci
2321cb0ef41Sopenharmony_ci/**
2331cb0ef41Sopenharmony_ci * Experimental API intended for the LongTasks UKM (crbug.com/1173527).
2341cb0ef41Sopenharmony_ci * The Reset() method should be called at the start of a potential
2351cb0ef41Sopenharmony_ci * long task. The Get() method returns durations of V8 work that
2361cb0ef41Sopenharmony_ci * happened during the task.
2371cb0ef41Sopenharmony_ci *
2381cb0ef41Sopenharmony_ci * This API is experimental and may be removed/changed in the future.
2391cb0ef41Sopenharmony_ci */
2401cb0ef41Sopenharmony_cistruct V8_EXPORT LongTaskStats {
2411cb0ef41Sopenharmony_ci  /**
2421cb0ef41Sopenharmony_ci   * Resets durations of V8 work for the new task.
2431cb0ef41Sopenharmony_ci   */
2441cb0ef41Sopenharmony_ci  V8_INLINE static void Reset(Isolate* isolate) {
2451cb0ef41Sopenharmony_ci    v8::internal::Internals::IncrementLongTasksStatsCounter(isolate);
2461cb0ef41Sopenharmony_ci  }
2471cb0ef41Sopenharmony_ci
2481cb0ef41Sopenharmony_ci  /**
2491cb0ef41Sopenharmony_ci   * Returns durations of V8 work that happened since the last Reset().
2501cb0ef41Sopenharmony_ci   */
2511cb0ef41Sopenharmony_ci  static LongTaskStats Get(Isolate* isolate);
2521cb0ef41Sopenharmony_ci
2531cb0ef41Sopenharmony_ci  int64_t gc_full_atomic_wall_clock_duration_us = 0;
2541cb0ef41Sopenharmony_ci  int64_t gc_full_incremental_wall_clock_duration_us = 0;
2551cb0ef41Sopenharmony_ci  int64_t gc_young_wall_clock_duration_us = 0;
2561cb0ef41Sopenharmony_ci  // Only collected with --slow-histograms
2571cb0ef41Sopenharmony_ci  int64_t v8_execute_us = 0;
2581cb0ef41Sopenharmony_ci};
2591cb0ef41Sopenharmony_ci
2601cb0ef41Sopenharmony_ci}  // namespace metrics
2611cb0ef41Sopenharmony_ci}  // namespace v8
2621cb0ef41Sopenharmony_ci
2631cb0ef41Sopenharmony_ci#endif  // V8_METRICS_H_
264