Commit 26cd041c authored by Siddhartha's avatar Siddhartha Committed by Commit Bot

Store renderer OOM metrics in shared memory buffer

The renderer OOM metrics are stored in shared memory buffer so that the
browser can read the metrics after renderer crashes (by OOM).

BUG=843419

Change-Id: I498256e473785051724efa80864f0292cc24362e
Reviewed-on: https://chromium-review.googlesource.com/1062211
Commit-Queue: Siddhartha S <ssid@chromium.org>
Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Reviewed-by: default avatarKentaro Hara <haraken@chromium.org>
Cr-Commit-Position: refs/heads/master@{#560219}
parent 9921a22f
include_rules = [
"+third_party/blink/common/oom_intervention"
]
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h" #include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents.h"
#include "third_party/blink/common/oom_intervention/oom_intervention_types.h"
DEFINE_WEB_CONTENTS_USER_DATA_KEY(OomInterventionTabHelper); DEFINE_WEB_CONTENTS_USER_DATA_KEY(OomInterventionTabHelper);
...@@ -102,6 +103,9 @@ OomInterventionTabHelper::OomInterventionTabHelper( ...@@ -102,6 +103,9 @@ OomInterventionTabHelper::OomInterventionTabHelper(
renderer_memory_workload_threshold_(GetRendererMemoryWorkloadThreshold()), renderer_memory_workload_threshold_(GetRendererMemoryWorkloadThreshold()),
weak_ptr_factory_(this) { weak_ptr_factory_(this) {
OutOfMemoryReporter::FromWebContents(web_contents)->AddObserver(this); OutOfMemoryReporter::FromWebContents(web_contents)->AddObserver(this);
shared_metrics_buffer_ = base::UnsafeSharedMemoryRegion::Create(
sizeof(blink::OomInterventionMetrics));
metrics_mapping_ = shared_metrics_buffer_.Map();
} }
OomInterventionTabHelper::~OomInterventionTabHelper() = default; OomInterventionTabHelper::~OomInterventionTabHelper() = default;
...@@ -300,9 +304,9 @@ void OomInterventionTabHelper::StartDetectionInRenderer() { ...@@ -300,9 +304,9 @@ void OomInterventionTabHelper::StartDetectionInRenderer() {
DCHECK(!binding_.is_bound()); DCHECK(!binding_.is_bound());
blink::mojom::OomInterventionHostPtr host; blink::mojom::OomInterventionHostPtr host;
binding_.Bind(mojo::MakeRequest(&host)); binding_.Bind(mojo::MakeRequest(&host));
intervention_->StartDetection(std::move(host), intervention_->StartDetection(
renderer_memory_workload_threshold_, std::move(host), shared_metrics_buffer_.Duplicate(),
trigger_intervention); renderer_memory_workload_threshold_, trigger_intervention);
} }
void OomInterventionTabHelper::OnNearOomDetected() { void OomInterventionTabHelper::OnNearOomDetected() {
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#ifndef CHROME_BROWSER_ANDROID_OOM_INTERVENTION_OOM_INTERVENTION_TAB_HELPER_H_ #ifndef CHROME_BROWSER_ANDROID_OOM_INTERVENTION_OOM_INTERVENTION_TAB_HELPER_H_
#define CHROME_BROWSER_ANDROID_OOM_INTERVENTION_OOM_INTERVENTION_TAB_HELPER_H_ #define CHROME_BROWSER_ANDROID_OOM_INTERVENTION_OOM_INTERVENTION_TAB_HELPER_H_
#include "base/memory/unsafe_shared_memory_region.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "base/optional.h" #include "base/optional.h"
#include "base/time/time.h" #include "base/time/time.h"
...@@ -105,6 +106,12 @@ class OomInterventionTabHelper ...@@ -105,6 +106,12 @@ class OomInterventionTabHelper
mojo::Binding<blink::mojom::OomInterventionHost> binding_; mojo::Binding<blink::mojom::OomInterventionHost> binding_;
// The shared memory region that stores metrics written by the renderer
// process. The memory is updated frequently and the browser should touch the
// memory only after renderer process is dead.
base::UnsafeSharedMemoryRegion shared_metrics_buffer_;
base::WritableSharedMemoryMapping metrics_mapping_;
// If memory workload in renderer is above this threshold, we assume that we // If memory workload in renderer is above this threshold, we assume that we
// are in a near-OOM situation. // are in a near-OOM situation.
uint64_t renderer_memory_workload_threshold_; uint64_t renderer_memory_workload_threshold_;
......
...@@ -32,6 +32,7 @@ jumbo_source_set("common") { ...@@ -32,6 +32,7 @@ jumbo_source_set("common") {
"message_port/transferable_message_struct_traits.cc", "message_port/transferable_message_struct_traits.cc",
"message_port/transferable_message_struct_traits.h", "message_port/transferable_message_struct_traits.h",
"mime_util/mime_util.cc", "mime_util/mime_util.cc",
"oom_intervention/oom_intervention_types.h",
"origin_manifest/origin_manifest.cc", "origin_manifest/origin_manifest.cc",
"origin_trials/trial_token.cc", "origin_trials/trial_token.cc",
"origin_trials/trial_token_validator.cc", "origin_trials/trial_token_validator.cc",
......
// Copyright 2018 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_COMMON_OOM_INTERVENTION_OOM_INTERVENTION_TYPES_H_
#define THIRD_PARTY_BLINK_COMMON_OOM_INTERVENTION_OOM_INTERVENTION_TYPES_H_
#include <stdint.h>
namespace blink {
// The struct with renderer metrics that are used to detect OOMs. This is stored
// in shared memory so that browser can read it even after the renderer dies.
struct OomInterventionMetrics {
uint64_t current_private_footprint_kb;
uint64_t current_swap_kb;
// Stores the total of V8, BlinkGC and PartitionAlloc memory usage.
uint64_t current_blink_usage_kb;
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_COMMON_OOM_INTERVENTION_OOM_INTERVENTION_TYPES_H_
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
module blink.mojom; module blink.mojom;
import "mojo/public/mojom/base/shared_memory.mojom";
// There are two phases to estimate a near-OOM situation. First phase takes // There are two phases to estimate a near-OOM situation. First phase takes
// place in the browser process. When the browser detects a high memory // place in the browser process. When the browser detects a high memory
// pressure it starts the second phase in the foreground renderer process, // pressure it starts the second phase in the foreground renderer process,
...@@ -27,8 +29,11 @@ interface OomIntervention { ...@@ -27,8 +29,11 @@ interface OomIntervention {
// Starts monitoring memory usage in renderer side. When the renderer's // Starts monitoring memory usage in renderer side. When the renderer's
// memory usage exceeds |memory_workload_threshold| (in bytes) the renderer // memory usage exceeds |memory_workload_threshold| (in bytes) the renderer
// calls host->OnHighMemoryUsage(). The renderer also triggers OOM // calls host->OnHighMemoryUsage(). The renderer also triggers OOM
// intervention when |trigger_intervention| is true. // intervention when |trigger_intervention| is true. |shared_metrics_buffer|
// stores the OomInterventionMetrics struct in shared memory. The buffer is
// expected to be upated very often with memory metrics.
StartDetection(OomInterventionHost host, StartDetection(OomInterventionHost host,
mojo_base.mojom.UnsafeSharedMemoryRegion shared_metrics_buffer,
uint64 memory_workload_threshold, uint64 memory_workload_threshold,
bool trigger_intervention); bool trigger_intervention);
}; };
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/controller/oom_intervention_impl.h" #include "third_party/blink/renderer/controller/oom_intervention_impl.h"
#include "mojo/public/cpp/bindings/strong_binding.h" #include "mojo/public/cpp/bindings/strong_binding.h"
#include "third_party/blink/common/oom_intervention/oom_intervention_types.h"
#include "third_party/blink/public/platform/platform.h" #include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h" #include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h"
#include "third_party/blink/renderer/platform/heap/handle.h" #include "third_party/blink/renderer/platform/heap/handle.h"
...@@ -53,9 +54,11 @@ OomInterventionImpl::~OomInterventionImpl() = default; ...@@ -53,9 +54,11 @@ OomInterventionImpl::~OomInterventionImpl() = default;
void OomInterventionImpl::StartDetection( void OomInterventionImpl::StartDetection(
mojom::blink::OomInterventionHostPtr host, mojom::blink::OomInterventionHostPtr host,
base::UnsafeSharedMemoryRegion shared_metrics_buffer,
uint64_t memory_workload_threshold, uint64_t memory_workload_threshold,
bool trigger_intervention) { bool trigger_intervention) {
host_ = std::move(host); host_ = std::move(host);
shared_metrics_buffer_ = shared_metrics_buffer.Map();
memory_workload_threshold_ = memory_workload_threshold; memory_workload_threshold_ = memory_workload_threshold;
trigger_intervention_ = trigger_intervention; trigger_intervention_ = trigger_intervention;
...@@ -76,6 +79,13 @@ void OomInterventionImpl::Check(TimerBase*) { ...@@ -76,6 +79,13 @@ void OomInterventionImpl::Check(TimerBase*) {
pauser_.reset(new ScopedPagePauser); pauser_.reset(new ScopedPagePauser);
} }
} }
// No memory barrier is used to write to this memory to avoid overhead. It is
// ok if browser reads slightly stale metrics since it is updated every
// second.
OomInterventionMetrics* metrics_shm =
static_cast<OomInterventionMetrics*>(shared_metrics_buffer_.memory());
metrics_shm->current_blink_usage_kb = workload / 1024;
} }
} // namespace blink } // namespace blink
...@@ -28,6 +28,7 @@ class CONTROLLER_EXPORT OomInterventionImpl ...@@ -28,6 +28,7 @@ class CONTROLLER_EXPORT OomInterventionImpl
// mojom::blink::OomIntervention: // mojom::blink::OomIntervention:
void StartDetection(mojom::blink::OomInterventionHostPtr, void StartDetection(mojom::blink::OomInterventionHostPtr,
base::UnsafeSharedMemoryRegion shared_metrics_buffer,
uint64_t memory_workload_threshold, uint64_t memory_workload_threshold,
bool trigger_intervention) override; bool trigger_intervention) override;
...@@ -38,6 +39,8 @@ class CONTROLLER_EXPORT OomInterventionImpl ...@@ -38,6 +39,8 @@ class CONTROLLER_EXPORT OomInterventionImpl
uint64_t memory_workload_threshold_ = 0; uint64_t memory_workload_threshold_ = 0;
base::WritableSharedMemoryMapping shared_metrics_buffer_;
MemoryWorkloadCaculator workload_calculator_; MemoryWorkloadCaculator workload_calculator_;
mojom::blink::OomInterventionHostPtr host_; mojom::blink::OomInterventionHostPtr host_;
bool trigger_intervention_ = false; bool trigger_intervention_ = false;
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "mojo/public/cpp/bindings/binding.h" #include "mojo/public/cpp/bindings/binding.h"
#include "services/service_manager/public/cpp/interface_provider.h" #include "services/service_manager/public/cpp/interface_provider.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/common/oom_intervention/oom_intervention_types.h"
#include "third_party/blink/renderer/core/exported/web_view_impl.h" #include "third_party/blink/renderer/core/exported/web_view_impl.h"
#include "third_party/blink/renderer/core/frame/frame_test_helpers.h" #include "third_party/blink/renderer/core/frame/frame_test_helpers.h"
#include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/core/frame/local_frame.h"
...@@ -60,7 +61,9 @@ TEST_F(OomInterventionImplTest, DetectedAndDeclined) { ...@@ -60,7 +61,9 @@ TEST_F(OomInterventionImplTest, DetectedAndDeclined) {
mojom::blink::OomInterventionHostPtr host_ptr; mojom::blink::OomInterventionHostPtr host_ptr;
MockOomInterventionHost mock_host(mojo::MakeRequest(&host_ptr)); MockOomInterventionHost mock_host(mojo::MakeRequest(&host_ptr));
intervention->StartDetection(std::move(host_ptr), threshold, base::UnsafeSharedMemoryRegion shm =
base::UnsafeSharedMemoryRegion::Create(sizeof(OomInterventionMetrics));
intervention->StartDetection(std::move(host_ptr), std::move(shm), threshold,
true /*trigger_intervention*/); true /*trigger_intervention*/);
test::RunDelayedTasks(TimeDelta::FromSeconds(1)); test::RunDelayedTasks(TimeDelta::FromSeconds(1));
EXPECT_TRUE(page->Paused()); EXPECT_TRUE(page->Paused());
......
...@@ -46,8 +46,10 @@ _CONFIG = [ ...@@ -46,8 +46,10 @@ _CONFIG = [
'base::TimeDelta', 'base::TimeDelta',
'base::TimeTicks', 'base::TimeTicks',
'base::UnguessableToken', 'base::UnguessableToken',
'base::UnsafeSharedMemoryRegion',
'base::WeakPtr', 'base::WeakPtr',
'base::WeakPtrFactory', 'base::WeakPtrFactory',
'base::WritableSharedMemoryMapping',
'base::in_place', 'base::in_place',
'base::make_optional', 'base::make_optional',
'base::make_span', 'base::make_span',
......
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