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