Commit 1165c7f7 authored by Joe Mason's avatar Joe Mason Committed by Chromium LUCI CQ

[PM] Add WebMemoryStressTester

This will call WebMeasureMemory randomly after a page load, and discard
the results, to check for crashes. It is controlled by an experiment
feature ("StressTestWebMeasureMemory") that will only be enabled for
some Canary users.

Also removes some unused headers from performance_manager_lifetime.cc.

Bug: 1085129
Change-Id: I32f24d4bf35032dea26b672a4fa899c5bf182cf3
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2627360Reviewed-by: default avatarSigurður Ásgeirsson <siggi@chromium.org>
Reviewed-by: default avatarUlan Degenbaev <ulan@chromium.org>
Commit-Queue: Joe Mason <joenotcharles@chromium.org>
Cr-Commit-Position: refs/heads/master@{#843099}
parent 3256b87d
......@@ -168,6 +168,8 @@ static_library("performance_manager") {
"v8_memory/web_memory_aggregator.h",
"v8_memory/web_memory_impl.cc",
"v8_memory/web_memory_impl.h",
"v8_memory/web_memory_stress_tester.cc",
"v8_memory/web_memory_stress_tester.h",
"web_contents_proxy.cc",
"web_contents_proxy_impl.cc",
"web_contents_proxy_impl.h",
......
......@@ -20,6 +20,7 @@
#include "components/performance_manager/public/decorators/tab_properties_decorator.h"
#include "components/performance_manager/public/graph/graph.h"
#include "components/performance_manager/v8_memory/v8_context_tracker.h"
#include "components/performance_manager/v8_memory/web_memory_stress_tester.h"
#if !defined(OS_ANDROID)
#include "components/performance_manager/public/decorators/site_data_recorder.h"
......@@ -69,8 +70,11 @@ void GraphFeaturesHelper::ConfigureGraph(Graph* graph) const {
Install<execution_context_priority::ExecutionContextPriorityDecorator>(
graph);
}
if (flags_.v8_context_tracker)
if (flags_.v8_context_tracker) {
Install<v8_memory::V8ContextTracker>(graph);
if (v8_memory::WebMeasureMemoryStressTester::FeatureIsEnabled())
Install<v8_memory::WebMeasureMemoryStressTester>(graph);
}
}
} // namespace performance_manager
......@@ -7,7 +7,6 @@
#include "base/bind.h"
#include "base/no_destructor.h"
#include "base/notreached.h"
#include "build/build_config.h"
#include "components/performance_manager/decorators/frame_visibility_decorator.h"
#include "components/performance_manager/decorators/page_load_tracker_decorator.h"
#include "components/performance_manager/embedder/graph_features_helper.h"
......@@ -22,10 +21,6 @@
#include "components/performance_manager/public/graph/graph.h"
#include "components/performance_manager/v8_memory/v8_context_tracker.h"
#if !defined(OS_ANDROID)
#include "components/performance_manager/public/decorators/site_data_recorder.h"
#endif
namespace performance_manager {
namespace {
......
// Copyright 2021 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 "components/performance_manager/v8_memory/web_memory_stress_tester.h"
#include <memory>
#include <string>
#include <utility>
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/check.h"
#include "base/dcheck_is_on.h"
#include "base/debug/activity_tracker.h"
#include "base/debug/dump_without_crashing.h"
#include "base/feature_list.h"
#include "base/memory/weak_ptr.h"
#include "base/metrics/field_trial_params.h"
#include "base/rand_util.h"
#include "components/performance_manager/graph/frame_node_impl.h"
#include "components/performance_manager/public/graph/frame_node.h"
#include "components/performance_manager/public/graph/page_node.h"
#include "components/performance_manager/public/mojom/web_memory.mojom.h"
#include "components/performance_manager/public/v8_memory/web_memory.h"
#include "mojo/public/cpp/bindings/message.h"
namespace performance_manager {
namespace v8_memory {
namespace {
#if DCHECK_IS_ON()
// Give the feature a different name on the Albatross build so it can get
// different parameters.
constexpr base::Feature kStressTestFeature{"StressTestWebMeasureMemoryDcheck",
base::FEATURE_DISABLED_BY_DEFAULT};
#else
constexpr base::Feature kStressTestFeature{"StressTestWebMeasureMemory",
base::FEATURE_DISABLED_BY_DEFAULT};
#endif
constexpr base::FeatureParam<double> kStressTestProbabilityParam{
&kStressTestFeature, "probability", 0.0};
class StressTestSecurityChecker : public WebMeasureMemorySecurityChecker {
public:
StressTestSecurityChecker() = default;
~StressTestSecurityChecker() override = default;
void CheckMeasureMemoryIsAllowed(
const FrameNode* frame_node,
MeasureMemoryCallback measure_memory_callback,
mojo::ReportBadMessageCallback bad_message_callback) const override {
// No need for a security check since we are not reporting results to the
// renderer.
DCHECK(frame_node);
DCHECK_ON_GRAPH_SEQUENCE(frame_node->GetGraph());
std::move(measure_memory_callback)
.Run(FrameNodeImpl::FromNode(frame_node)->GetWeakPtr());
}
};
// When the production implementation would kill a renderer, instead upload a
// crash report with the message in a breadcrumb. This should only be done once
// per browser session to avoid spamming crashes.
void ReportBadMessageInCrashOnce(const std::string& message) {
static bool have_crashed = false;
if (have_crashed)
return;
base::debug::ScopedActivity scoped_activity;
auto& user_data = scoped_activity.user_data();
user_data.SetString("web_measure_memory_bad_mojo_message", message);
// Crashes here should be assigned to https://crbug.com/1085129 for
// investigation.
base::debug::DumpWithoutCrashing();
}
} // namespace
// static
bool WebMeasureMemoryStressTester::FeatureIsEnabled() {
return base::FeatureList::IsEnabled(kStressTestFeature);
}
void WebMeasureMemoryStressTester::OnLoadingStateChanged(
const PageNode* page_node) {
DCHECK(page_node);
DCHECK_ON_GRAPH_SEQUENCE(page_node->GetGraph());
if (page_node->GetLoadingState() != PageNode::LoadingState::kLoadedIdle)
return;
const FrameNode* main_frame = page_node->GetMainFrameNode();
if (!main_frame)
return;
if (base::RandDouble() > kStressTestProbabilityParam.Get())
return;
WebMeasureMemory(main_frame, mojom::WebMemoryMeasurement::Mode::kDefault,
std::make_unique<StressTestSecurityChecker>(),
/*result_callback=*/base::DoNothing(),
base::BindOnce(&ReportBadMessageInCrashOnce));
}
void WebMeasureMemoryStressTester::OnPassedToGraph(Graph* graph) {
graph->AddPageNodeObserver(this);
}
void WebMeasureMemoryStressTester::OnTakenFromGraph(Graph* graph) {
graph->RemovePageNodeObserver(this);
}
} // namespace v8_memory
} // namespace performance_manager
// Copyright 2021 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 COMPONENTS_PERFORMANCE_MANAGER_V8_MEMORY_WEB_MEMORY_STRESS_TESTER_H_
#define COMPONENTS_PERFORMANCE_MANAGER_V8_MEMORY_WEB_MEMORY_STRESS_TESTER_H_
#include "components/performance_manager/public/graph/graph.h"
#include "components/performance_manager/public/graph/page_node.h"
namespace performance_manager {
namespace v8_memory {
// Observer that calls WebMeasureMemory randomly after a page load, and
// discards the results, to check for crashes. This is controlled by an
// experiment that will only be enabled for some Canary users.
class WebMeasureMemoryStressTester : public PageNode::ObserverDefaultImpl,
public GraphOwned {
public:
static bool FeatureIsEnabled();
WebMeasureMemoryStressTester() = default;
~WebMeasureMemoryStressTester() override = default;
WebMeasureMemoryStressTester(const WebMeasureMemoryStressTester& other) =
delete;
WebMeasureMemoryStressTester& operator=(
const WebMeasureMemoryStressTester& other) = delete;
// PageNode::ObserverDefaultImpl
void OnLoadingStateChanged(const PageNode* page_node) override;
// GraphOwned
void OnPassedToGraph(Graph* graph) override;
void OnTakenFromGraph(Graph* graph) override;
};
} // namespace v8_memory
} // namespace performance_manager
#endif // COMPONENTS_PERFORMANCE_MANAGER_V8_MEMORY_WEB_MEMORY_STRESS_TESTER_H_
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