Commit 524a904c authored by Emanuel Ziegler's avatar Emanuel Ziegler Committed by Commit Bot

[ukm][wasm] Add event-based metric collection for V8/Wasm

Use V8's event-based metric collection to provide a recorder
for UKM events for Wasm.

Design doc: https://docs.google.com/document/d/1vCZQCh4B05isqwJOwTPv7WqcnVp4KJITMgsHSBg35ZI/
UKM collection review: https://docs.google.com/document/d/1Lkop99UNkA754knShPin9uP9kZJExwPXRy1jdj5IZjQ/

Bug: chromium:1101749
Bug: chromium:1092417

R=ulan@chromium.org
R=haraken@chromium.org
R=rkaplow@chromium.org

Change-Id: I48f8c272ba4a3305145710fb3068bf3d5c4273be
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2288561
Commit-Queue: Emanuel Ziegler <ecmziegler@chromium.org>
Reviewed-by: default avatarKentaro Hara <haraken@chromium.org>
Reviewed-by: default avatarRobert Kaplow <rkaplow@chromium.org>
Reviewed-by: default avatarUlan Degenbaev <ulan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#795417}
parent cd3b0f7d
......@@ -149,6 +149,8 @@ bindings_core_v8_files =
"core/v8/v8_intersection_observer_delegate.h",
"core/v8/v8_iterator_result_value.cc",
"core/v8/v8_iterator_result_value.h",
"core/v8/v8_metrics.cc",
"core/v8/v8_metrics.h",
"core/v8/v8_object_builder.cc",
"core/v8/v8_object_builder.h",
"core/v8/v8_object_parser.cc",
......
......@@ -33,8 +33,6 @@
#include "base/memory/scoped_refptr.h"
#include "base/metrics/histogram_macros.h"
#include "base/system/sys_info.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "services/metrics/public/cpp/ukm_recorder.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/bindings/core/v8/binding_security.h"
#include "third_party/blink/renderer/bindings/core/v8/isolated_world_csp.h"
......@@ -54,6 +52,7 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_error_event.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_gc_controller.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_idle_task_runner.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_metrics.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_trusted_script.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_wasm_response_extensions.h"
......@@ -757,6 +756,8 @@ void V8Initializer::InitializeMainThread(const intptr_t* reference_table) {
isolate->SetPromiseRejectCallback(PromiseRejectHandlerInMainThread);
isolate->SetMetricsRecorder(std::make_shared<V8MetricsRecorder>(isolate));
V8PerIsolateData::From(isolate)->SetThreadDebugger(
std::make_unique<MainThreadDebugger>(isolate));
}
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/bindings/core/v8/v8_metrics.h"
#include "services/metrics/public/cpp/metrics_utils.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/frame/frame.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/page/page.h"
namespace blink {
void V8MetricsRecorder::AddMainThreadEvent(
const v8::metrics::WasmModuleDecoded& event,
v8::metrics::Recorder::ContextId context_id) {
auto ukm = GetUkmRecorderAndSourceId(context_id);
if (!ukm)
return;
ukm::builders::V8_Wasm_ModuleDecoded(ukm->source_id)
.SetStreamed(event.streamed ? 1 : 0)
.SetSuccess(event.success ? 1 : 0)
.SetModuleSize(
ukm::GetExponentialBucketMinForBytes(event.module_size_in_bytes))
.SetFunctionCount(event.function_count)
.SetWallClockTime(event.wall_clock_time_in_us)
.Record(ukm->recorder);
}
void V8MetricsRecorder::AddMainThreadEvent(
const v8::metrics::WasmModuleCompiled& event,
v8::metrics::Recorder::ContextId context_id) {
auto ukm = GetUkmRecorderAndSourceId(context_id);
if (!ukm)
return;
ukm::builders::V8_Wasm_ModuleCompiled(ukm->source_id)
.SetAsync(event.async ? 1 : 0)
.SetCached(event.cached ? 1 : 0)
.SetDeserialized(event.deserialized ? 1 : 0)
.SetLazy(event.lazy ? 1 : 0)
.SetStreamed(event.streamed ? 1 : 0)
.SetSuccess(event.success ? 1 : 0)
.SetCodeSize(
ukm::GetExponentialBucketMinForBytes(event.code_size_in_bytes))
.SetLiftoffBailoutCount(event.liftoff_bailout_count)
.SetWallClockTime(event.wall_clock_time_in_us)
.Record(ukm->recorder);
}
void V8MetricsRecorder::AddMainThreadEvent(
const v8::metrics::WasmModuleInstantiated& event,
v8::metrics::Recorder::ContextId context_id) {
auto ukm = GetUkmRecorderAndSourceId(context_id);
if (!ukm)
return;
ukm::builders::V8_Wasm_ModuleInstantiated(ukm->source_id)
.SetSuccess(event.success ? 1 : 0)
.SetImportedFunctionCount(event.imported_function_count)
.SetWallClockTime(event.wall_clock_time_in_us)
.Record(ukm->recorder);
}
void V8MetricsRecorder::AddMainThreadEvent(
const v8::metrics::WasmModuleTieredUp& event,
v8::metrics::Recorder::ContextId context_id) {
auto ukm = GetUkmRecorderAndSourceId(context_id);
if (!ukm)
return;
ukm::builders::V8_Wasm_ModuleTieredUp(ukm->source_id)
.SetLazy(event.lazy ? 1 : 0)
.SetCodeSize(
ukm::GetExponentialBucketMinForBytes(event.code_size_in_bytes))
.SetWallClockTime(event.wall_clock_time_in_us)
.Record(ukm->recorder);
}
void V8MetricsRecorder::NotifyIsolateDisposal() {
v8::metrics::Recorder::NotifyIsolateDisposal();
isolate_ = nullptr;
}
Document* V8MetricsRecorder::GetDocument(
v8::metrics::Recorder::ContextId context_id) {
if (!isolate_)
return nullptr;
v8::HandleScope handle_scope(isolate_);
v8::MaybeLocal<v8::Context> maybe_context =
v8::metrics::Recorder::GetContext(isolate_, context_id);
if (maybe_context.IsEmpty())
return nullptr;
return To<LocalDOMWindow>(
ExecutionContext::From(maybe_context.ToLocalChecked()))
->document();
}
base::Optional<V8MetricsRecorder::UkmRecorderAndSourceId>
V8MetricsRecorder::GetUkmRecorderAndSourceId(
v8::metrics::Recorder::ContextId context_id) {
DCHECK(IsMainThread());
if (!isolate_)
return base::Optional<UkmRecorderAndSourceId>();
Document* document = GetDocument(context_id);
if (!document)
return base::Optional<UkmRecorderAndSourceId>();
ukm::UkmRecorder* ukm_recorder = document->UkmRecorder();
if (!ukm_recorder)
return base::Optional<UkmRecorderAndSourceId>();
return base::Optional<UkmRecorderAndSourceId>(base::in_place, ukm_recorder,
document->UkmSourceID());
}
} // namespace blink
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_V8_METRICS_H_
#define THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_V8_METRICS_H_
#include "services/metrics/public/cpp/ukm_recorder.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "v8/include/v8-metrics.h"
namespace blink {
class Document;
// Implements a V8 metrics recorder for gathering events generated
// within the V8 engine. This is used for some UMA and all UKM
// metrics. All event handling methods in here are run in the main
// thread, so thread-safety is not an issue and is handled by the
// V8 engine.
// For UKM events, the context is used to get the source id and the
// UKM recorder.
class CORE_EXPORT V8MetricsRecorder : public v8::metrics::Recorder {
public:
explicit V8MetricsRecorder(v8::Isolate* isolate) : isolate_(isolate) {}
void AddMainThreadEvent(const v8::metrics::WasmModuleDecoded& event,
ContextId context_id) override;
void AddMainThreadEvent(const v8::metrics::WasmModuleCompiled& event,
ContextId context_id) override;
void AddMainThreadEvent(const v8::metrics::WasmModuleInstantiated& event,
ContextId context_id) override;
void AddMainThreadEvent(const v8::metrics::WasmModuleTieredUp& event,
ContextId context_id) override;
void NotifyIsolateDisposal() override;
private:
struct UkmRecorderAndSourceId {
ukm::UkmRecorder* recorder;
ukm::SourceId source_id;
UkmRecorderAndSourceId(ukm::UkmRecorder* ukm_recorder,
ukm::SourceId ukm_source_id)
: recorder(ukm_recorder), source_id(ukm_source_id) {}
};
Document* GetDocument(ContextId context_id);
base::Optional<UkmRecorderAndSourceId> GetUkmRecorderAndSourceId(
ContextId context_id);
v8::Isolate* isolate_;
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_V8_METRICS_H_
......@@ -12462,6 +12462,307 @@ be describing additional metrics about the same event.
</metric>
</event>
<event name="V8.Wasm.ModuleCompiled">
<owner>ecmziegler@chromium.org</owner>
<summary>
Records information on baseline compilation of WebAssembly modules and its
resource consumption.
</summary>
<metric name="Async" enum="Boolean">
<summary>
The compilation was running asynchronously.
</summary>
<aggregation>
<history>
<index fields="profile.form_factor"/>
<statistics>
<enumeration/>
</statistics>
</history>
</aggregation>
</metric>
<metric name="Cached" enum="Boolean">
<summary>
The compilation was re-using already cached native module code instead of
JIT compiling it.
</summary>
<aggregation>
<history>
<index fields="profile.form_factor"/>
<statistics>
<enumeration/>
</statistics>
</history>
</aggregation>
</metric>
<metric name="CodeSize">
<summary>
The size of the native module code in bytes after baseline compilation
finished.
</summary>
<aggregation>
<history>
<index fields="profile.form_factor"/>
<statistics>
<quantiles type="std-percentiles"/>
</statistics>
</history>
</aggregation>
</metric>
<metric name="Deserialized" enum="Boolean">
<summary>
The compilation was deserializing the native module code from the disk
cache instead of JIT compiling it.
</summary>
<aggregation>
<history>
<index fields="profile.form_factor"/>
<statistics>
<enumeration/>
</statistics>
</history>
</aggregation>
</metric>
<metric name="Lazy" enum="Boolean">
<summary>
The lazy compilation flag was enabled and therefore not all functions
might have been compiled.
</summary>
<aggregation>
<history>
<index fields="profile.form_factor"/>
<statistics>
<enumeration/>
</statistics>
</history>
</aggregation>
</metric>
<metric name="LiftoffBailoutCount">
<summary>
The number of functions that Liftoff could not compile and that therefore
needed to be compiled by TurboFan.
</summary>
<aggregation>
<history>
<index fields="profile.form_factor"/>
<statistics>
<quantiles type="std-percentiles"/>
</statistics>
</history>
</aggregation>
</metric>
<metric name="Streamed" enum="Boolean">
<summary>
The wire bytes were streamed while compiling.
</summary>
<aggregation>
<history>
<index fields="profile.form_factor"/>
<statistics>
<enumeration/>
</statistics>
</history>
</aggregation>
</metric>
<metric name="Success" enum="Boolean">
<summary>
The module was successfully compiled.
</summary>
<aggregation>
<history>
<index fields="profile.form_factor"/>
<index fields="profile.system_ram"/>
<statistics>
<enumeration/>
</statistics>
</history>
</aggregation>
</metric>
<metric name="WallClockTime">
<summary>
The total time the compilation took in microseconds.
</summary>
<aggregation>
<history>
<index fields="profile.form_factor"/>
<statistics>
<quantiles type="std-percentiles"/>
</statistics>
</history>
</aggregation>
</metric>
</event>
<event name="V8.Wasm.ModuleDecoded">
<owner>ecmziegler@chromium.org</owner>
<summary>
Records information on WebAssembly modules included in websites.
</summary>
<metric name="FunctionCount">
<summary>
Number of declared functions in this module.
</summary>
<aggregation>
<history>
<index fields="profile.form_factor"/>
<statistics>
<quantiles type="std-percentiles"/>
</statistics>
</history>
</aggregation>
</metric>
<metric name="ModuleSize">
<summary>
The size of the wire bytes of the module.
</summary>
<aggregation>
<history>
<index fields="profile.form_factor"/>
<statistics>
<quantiles type="std-percentiles"/>
</statistics>
</history>
</aggregation>
</metric>
<metric name="Streamed" enum="Boolean">
<summary>
The wire bytes were streamed while decoding.
</summary>
<aggregation>
<history>
<index fields="profile.form_factor"/>
<statistics>
<enumeration/>
</statistics>
</history>
</aggregation>
</metric>
<metric name="Success" enum="Boolean">
<summary>
The module was successfully decoded.
</summary>
<aggregation>
<history>
<index fields="profile.form_factor"/>
<index fields="profile.system_ram"/>
<statistics>
<enumeration/>
</statistics>
</history>
</aggregation>
</metric>
<metric name="WallClockTime">
<summary>
The total time the decoding took in microseconds.
</summary>
<aggregation>
<history>
<index fields="profile.form_factor"/>
<statistics>
<quantiles type="std-percentiles"/>
</statistics>
</history>
</aggregation>
</metric>
</event>
<event name="V8.Wasm.ModuleInstantiated">
<owner>ecmziegler@chromium.org</owner>
<summary>
Records information on instantiation of WebAssembly modules and its resource
consumption.
</summary>
<metric name="ImportedFunctionCount">
<summary>
The number of functions imported by the module.
</summary>
<aggregation>
<history>
<index fields="profile.form_factor"/>
<statistics>
<quantiles type="std-percentiles"/>
</statistics>
</history>
</aggregation>
</metric>
<metric name="Success" enum="Boolean">
<summary>
The module was successfully instantiated.
</summary>
<aggregation>
<history>
<index fields="profile.form_factor"/>
<index fields="profile.system_ram"/>
<statistics>
<enumeration/>
</statistics>
</history>
</aggregation>
</metric>
<metric name="WallClockTime">
<summary>
The total time the instantiation took in microseconds.
</summary>
<aggregation>
<history>
<index fields="profile.form_factor"/>
<statistics>
<quantiles type="std-percentiles"/>
</statistics>
</history>
</aggregation>
</metric>
</event>
<event name="V8.Wasm.ModuleTieredUp">
<owner>ecmziegler@chromium.org</owner>
<summary>
Records information on top-tier compilation of WebAssembly modules and its
resource consumption.
</summary>
<metric name="CodeSize">
<summary>
The size of the native module code in bytes after top-tier compilation
finished.
</summary>
<aggregation>
<history>
<index fields="profile.form_factor"/>
<statistics>
<quantiles type="std-percentiles"/>
</statistics>
</history>
</aggregation>
</metric>
<metric name="Lazy" enum="Boolean">
<summary>
The lazy compilation flag was enabled and therefore not all functions
might have been compiled.
</summary>
<aggregation>
<history>
<index fields="profile.form_factor"/>
<statistics>
<enumeration/>
</statistics>
</history>
</aggregation>
</metric>
<metric name="WallClockTime">
<summary>
The total time the compilation took in microseconds.
</summary>
<aggregation>
<history>
<index fields="profile.form_factor"/>
<statistics>
<quantiles type="std-percentiles"/>
</statistics>
</history>
</aggregation>
</metric>
</event>
<event name="VirtualKeyboard.Open">
<owner>shend@chromium.org</owner>
<summary>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment