Commit aa469566 authored by Keishi Hattori's avatar Keishi Hattori Committed by Commit Bot

Use MemoryUsageMonitor for oom intervention and crash memory metrics

Use MemoryUsageMonitor from OomInterventionImpl and CrashMemoryMetricsReporter

Bug: 920922
Change-Id: Iff9f69d87b870ea6acc6c760058745de0d1a052a
Reviewed-on: https://chromium-review.googlesource.com/c/1411392
Commit-Queue: Keishi Hattori <keishi@chromium.org>
Reviewed-by: default avatarKentaro Hara <haraken@chromium.org>
Reviewed-by: default avatarYuzu Saijo <yuzus@chromium.org>
Cr-Commit-Position: refs/heads/master@{#626845}
parent a685a70f
...@@ -4,10 +4,6 @@ ...@@ -4,10 +4,6 @@
#include "third_party/blink/renderer/controller/crash_memory_metrics_reporter_impl.h" #include "third_party/blink/renderer/controller/crash_memory_metrics_reporter_impl.h"
#include <ctype.h>
#include <fcntl.h>
#include <unistd.h>
#include "base/allocator/partition_allocator/oom_callback.h" #include "base/allocator/partition_allocator/oom_callback.h"
#include "base/metrics/histogram_macros.h" #include "base/metrics/histogram_macros.h"
#include "base/process/memory.h" #include "base/process/memory.h"
...@@ -20,25 +16,6 @@ ...@@ -20,25 +16,6 @@
namespace blink { namespace blink {
namespace {
// Roughly calculates amount of memory which is used to execute pages.
uint64_t BlinkMemoryWorkloadCalculator() {
v8::Isolate* isolate = V8PerIsolateData::MainThreadIsolate();
DCHECK(isolate);
v8::HeapStatistics heap_statistics;
isolate->GetHeapStatistics(&heap_statistics);
// TODO: Add memory usage for worker threads.
size_t v8_size =
heap_statistics.total_heap_size() + heap_statistics.malloced_memory();
size_t blink_gc_size = ProcessHeap::TotalAllocatedObjectSize() +
ProcessHeap::TotalMarkedObjectSize();
size_t partition_alloc_size = WTF::Partitions::TotalSizeOfCommittedPages();
return v8_size + blink_gc_size + partition_alloc_size;
}
} // namespace
// static // static
void CrashMemoryMetricsReporterImpl::Bind( void CrashMemoryMetricsReporterImpl::Bind(
mojom::blink::CrashMemoryMetricsReporterRequest request) { mojom::blink::CrashMemoryMetricsReporterRequest request) {
...@@ -68,6 +45,11 @@ void CrashMemoryMetricsReporterImpl::SetSharedMemory( ...@@ -68,6 +45,11 @@ void CrashMemoryMetricsReporterImpl::SetSharedMemory(
shared_metrics_mapping_ = shared_metrics_buffer.Map(); shared_metrics_mapping_ = shared_metrics_buffer.Map();
} }
void CrashMemoryMetricsReporterImpl::OnMemoryPing(MemoryUsage usage) {
WriteIntoSharedMemory(
CrashMemoryMetricsReporterImpl::MemoryUsageToMetrics(usage));
}
void CrashMemoryMetricsReporterImpl::WriteIntoSharedMemory( void CrashMemoryMetricsReporterImpl::WriteIntoSharedMemory(
const OomInterventionMetrics& metrics) { const OomInterventionMetrics& metrics) {
if (!shared_metrics_mapping_.IsValid()) if (!shared_metrics_mapping_.IsValid())
...@@ -96,31 +78,30 @@ void CrashMemoryMetricsReporterImpl::OnOOMCallback() { ...@@ -96,31 +78,30 @@ void CrashMemoryMetricsReporterImpl::OnOOMCallback() {
OomInterventionMetrics OomInterventionMetrics
CrashMemoryMetricsReporterImpl::GetCurrentMemoryMetrics() { CrashMemoryMetricsReporterImpl::GetCurrentMemoryMetrics() {
// This can only be called after ResetFileDescriptors(). return MemoryUsageToMetrics(
DCHECK(statm_fd_.is_valid() && status_fd_.is_valid()); MemoryUsageMonitor::Instance().GetCurrentMemoryUsage());
}
// static
OomInterventionMetrics CrashMemoryMetricsReporterImpl::MemoryUsageToMetrics(
MemoryUsage usage) {
OomInterventionMetrics metrics = {}; OomInterventionMetrics metrics = {};
metrics.current_blink_usage_kb = BlinkMemoryWorkloadCalculator() / 1024;
uint64_t private_footprint, swap, vm_size; DCHECK(!std::isnan(usage.private_footprint_bytes));
if (MemoryUsageMonitorAndroid::CalculateProcessMemoryFootprint( DCHECK(!std::isnan(usage.swap_bytes));
statm_fd_.get(), status_fd_.get(), &private_footprint, &swap, DCHECK(!std::isnan(usage.vm_size_bytes));
&vm_size)) { metrics.current_blink_usage_kb =
metrics.current_private_footprint_kb = private_footprint / 1024; (usage.v8_bytes + usage.blink_gc_bytes + usage.partition_alloc_bytes) /
metrics.current_swap_kb = swap / 1024; 1024;
metrics.current_vm_size_kb = vm_size / 1024;
} DCHECK(!std::isnan(usage.private_footprint_bytes));
DCHECK(!std::isnan(usage.swap_bytes));
DCHECK(!std::isnan(usage.vm_size_bytes));
metrics.current_private_footprint_kb = usage.private_footprint_bytes / 1024;
metrics.current_swap_kb = usage.swap_bytes / 1024;
metrics.current_vm_size_kb = usage.vm_size_bytes / 1024;
metrics.allocation_failed = 0; // false metrics.allocation_failed = 0; // false
return metrics; return metrics;
} }
bool CrashMemoryMetricsReporterImpl::ResetFileDiscriptors() {
// See https://goo.gl/KjWnZP For details about why we read these files from
// sandboxed renderer. Keep these files open when detection is enabled.
if (!statm_fd_.is_valid())
statm_fd_.reset(open("/proc/self/statm", O_RDONLY));
if (!status_fd_.is_valid())
status_fd_.reset(open("/proc/self/status", O_RDONLY));
return !statm_fd_.is_valid() || !status_fd_.is_valid();
}
} // namespace blink } // namespace blink
...@@ -10,15 +10,18 @@ ...@@ -10,15 +10,18 @@
#include "third_party/blink/public/common/oom_intervention/oom_intervention_types.h" #include "third_party/blink/public/common/oom_intervention/oom_intervention_types.h"
#include "third_party/blink/public/mojom/crash/crash_memory_metrics_reporter.mojom-blink.h" #include "third_party/blink/public/mojom/crash/crash_memory_metrics_reporter.mojom-blink.h"
#include "third_party/blink/renderer/controller/controller_export.h" #include "third_party/blink/renderer/controller/controller_export.h"
#include "third_party/blink/renderer/controller/memory_usage_monitor.h"
namespace blink { namespace blink {
// Writes data about renderer into shared memory that will be read by browser. // Writes data about renderer into shared memory that will be read by browser.
class CONTROLLER_EXPORT CrashMemoryMetricsReporterImpl class CONTROLLER_EXPORT CrashMemoryMetricsReporterImpl
: public mojom::blink::CrashMemoryMetricsReporter { : public mojom::blink::CrashMemoryMetricsReporter,
public MemoryUsageMonitor::Observer {
public: public:
static CrashMemoryMetricsReporterImpl& Instance(); static CrashMemoryMetricsReporterImpl& Instance();
static void Bind(mojom::blink::CrashMemoryMetricsReporterRequest); static void Bind(mojom::blink::CrashMemoryMetricsReporterRequest);
static OomInterventionMetrics MemoryUsageToMetrics(MemoryUsage);
~CrashMemoryMetricsReporterImpl() override; ~CrashMemoryMetricsReporterImpl() override;
...@@ -26,7 +29,8 @@ class CONTROLLER_EXPORT CrashMemoryMetricsReporterImpl ...@@ -26,7 +29,8 @@ class CONTROLLER_EXPORT CrashMemoryMetricsReporterImpl
void SetSharedMemory( void SetSharedMemory(
base::UnsafeSharedMemoryRegion shared_metrics_buffer) override; base::UnsafeSharedMemoryRegion shared_metrics_buffer) override;
void WriteIntoSharedMemory(const OomInterventionMetrics& metrics); // MemoryUsageMonitor::Observer:
void OnMemoryPing(MemoryUsage) override;
// This method tracks when an allocation failure occurs. It should be hooked // This method tracks when an allocation failure occurs. It should be hooked
// into all platform allocation failure handlers in a process such as // into all platform allocation failure handlers in a process such as
...@@ -38,22 +42,16 @@ class CONTROLLER_EXPORT CrashMemoryMetricsReporterImpl ...@@ -38,22 +42,16 @@ class CONTROLLER_EXPORT CrashMemoryMetricsReporterImpl
// This function needs to be called after ResetFileDescriptors. // This function needs to be called after ResetFileDescriptors.
OomInterventionMetrics GetCurrentMemoryMetrics(); OomInterventionMetrics GetCurrentMemoryMetrics();
// This function resets statm_fd_ & status_fd_ to prepare for getting metrics.
bool ResetFileDiscriptors();
protected: protected:
CrashMemoryMetricsReporterImpl(); CrashMemoryMetricsReporterImpl();
private: private:
FRIEND_TEST_ALL_PREFIXES(OomInterventionImplTest, CalculateProcessFootprint); FRIEND_TEST_ALL_PREFIXES(OomInterventionImplTest, CalculateProcessFootprint);
void WriteIntoSharedMemory(const OomInterventionMetrics& metrics);
base::WritableSharedMemoryMapping shared_metrics_mapping_; base::WritableSharedMemoryMapping shared_metrics_mapping_;
mojo::Binding<mojom::blink::CrashMemoryMetricsReporter> binding_; mojo::Binding<mojom::blink::CrashMemoryMetricsReporter> binding_;
// The file descriptor to current process proc files. The files are kept open
// when detection is on to reduce measurement overhead.
base::ScopedFD statm_fd_;
base::ScopedFD status_fd_;
}; };
} // namespace blink } // namespace blink
......
...@@ -28,6 +28,10 @@ void MemoryUsageMonitor::RemoveObserver(Observer* observer) { ...@@ -28,6 +28,10 @@ void MemoryUsageMonitor::RemoveObserver(Observer* observer) {
observers_.RemoveObserver(observer); observers_.RemoveObserver(observer);
} }
bool MemoryUsageMonitor::HasObserver(Observer* observer) {
return observers_.HasObserver(observer);
}
void MemoryUsageMonitor::StartMonitoringIfNeeded() { void MemoryUsageMonitor::StartMonitoringIfNeeded() {
if (timer_.IsActive()) if (timer_.IsActive())
return; return;
......
...@@ -36,12 +36,13 @@ class CONTROLLER_EXPORT MemoryUsageMonitor { ...@@ -36,12 +36,13 @@ class CONTROLLER_EXPORT MemoryUsageMonitor {
virtual ~MemoryUsageMonitor() = default; virtual ~MemoryUsageMonitor() = default;
// Returns the current memory usage. // Returns the current memory usage.
MemoryUsage GetCurrentMemoryUsage(); virtual MemoryUsage GetCurrentMemoryUsage();
// Ensures that an observer is only added once. // Ensures that an observer is only added once.
void AddObserver(Observer*); void AddObserver(Observer*);
// Observers must be removed before they are destroyed. // Observers must be removed before they are destroyed.
void RemoveObserver(Observer*); void RemoveObserver(Observer*);
bool HasObserver(Observer*);
bool TimerIsActive() const { return timer_.IsActive(); } bool TimerIsActive() const { return timer_.IsActive(); }
......
...@@ -11,10 +11,10 @@ ...@@ -11,10 +11,10 @@
#include "third_party/blink/public/platform/platform.h" #include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_gc_for_context_dispose.h" #include "third_party/blink/renderer/bindings/core/v8/v8_gc_for_context_dispose.h"
#include "third_party/blink/renderer/controller/crash_memory_metrics_reporter_impl.h" #include "third_party/blink/renderer/controller/crash_memory_metrics_reporter_impl.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/page/page.h" #include "third_party/blink/renderer/core/page/page.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/wtf/allocator/partitions.h"
namespace blink { namespace blink {
...@@ -25,14 +25,13 @@ void OomInterventionImpl::Create(mojom::blink::OomInterventionRequest request) { ...@@ -25,14 +25,13 @@ void OomInterventionImpl::Create(mojom::blink::OomInterventionRequest request) {
} }
OomInterventionImpl::OomInterventionImpl() OomInterventionImpl::OomInterventionImpl()
: timer_(Thread::MainThread()->GetTaskRunner(), : delayed_report_timer_(Thread::MainThread()->GetTaskRunner(),
this,
&OomInterventionImpl::Check),
delayed_report_timer_(Thread::MainThread()->GetTaskRunner(),
this, this,
&OomInterventionImpl::TimerFiredUMAReport) {} &OomInterventionImpl::TimerFiredUMAReport) {}
OomInterventionImpl::~OomInterventionImpl() {} OomInterventionImpl::~OomInterventionImpl() {
MemoryUsageMonitorInstance().RemoveObserver(this);
}
void OomInterventionImpl::StartDetection( void OomInterventionImpl::StartDetection(
mojom::blink::OomInterventionHostPtr host, mojom::blink::OomInterventionHostPtr host,
...@@ -42,26 +41,29 @@ void OomInterventionImpl::StartDetection( ...@@ -42,26 +41,29 @@ void OomInterventionImpl::StartDetection(
bool purge_v8_memory_enabled) { bool purge_v8_memory_enabled) {
host_ = std::move(host); host_ = std::move(host);
// Disable intervention if we cannot get memory details of current process.
if (CrashMemoryMetricsReporterImpl::Instance().ResetFileDiscriptors())
return;
detection_args_ = std::move(detection_args); detection_args_ = std::move(detection_args);
renderer_pause_enabled_ = renderer_pause_enabled; renderer_pause_enabled_ = renderer_pause_enabled;
navigate_ads_enabled_ = navigate_ads_enabled; navigate_ads_enabled_ = navigate_ads_enabled;
purge_v8_memory_enabled_ = purge_v8_memory_enabled; purge_v8_memory_enabled_ = purge_v8_memory_enabled;
timer_.Start(TimeDelta(), TimeDelta::FromSeconds(1), FROM_HERE); MemoryUsageMonitorInstance().AddObserver(this);
} }
OomInterventionMetrics OomInterventionImpl::GetCurrentMemoryMetrics() { MemoryUsageMonitor& OomInterventionImpl::MemoryUsageMonitorInstance() {
return CrashMemoryMetricsReporterImpl::Instance().GetCurrentMemoryMetrics(); return MemoryUsageMonitor::Instance();
} }
void OomInterventionImpl::Check(TimerBase*) { void OomInterventionImpl::OnMemoryPing(MemoryUsage usage) {
// Ignore pings without process memory usage information.
if (std::isnan(usage.private_footprint_bytes) ||
std::isnan(usage.swap_bytes) || std::isnan(usage.vm_size_bytes))
return;
Check(CrashMemoryMetricsReporterImpl::MemoryUsageToMetrics(usage));
}
void OomInterventionImpl::Check(OomInterventionMetrics current_memory) {
DCHECK(host_); DCHECK(host_);
OomInterventionMetrics current_memory = GetCurrentMemoryMetrics();
bool oom_detected = false; bool oom_detected = false;
oom_detected |= detection_args_->blink_workload_threshold > 0 && oom_detected |= detection_args_->blink_workload_threshold > 0 &&
...@@ -100,7 +102,7 @@ void OomInterventionImpl::Check(TimerBase*) { ...@@ -100,7 +102,7 @@ void OomInterventionImpl::Check(TimerBase*) {
} }
host_->OnHighMemoryUsage(); host_->OnHighMemoryUsage();
timer_.Stop(); MemoryUsageMonitorInstance().RemoveObserver(this);
// Send memory pressure notification to trigger GC. // Send memory pressure notification to trigger GC.
Thread::MainThread()->GetTaskRunner()->PostTask(FROM_HERE, Thread::MainThread()->GetTaskRunner()->PostTask(FROM_HERE,
base::BindOnce(&TriggerGC)); base::BindOnce(&TriggerGC));
...@@ -134,13 +136,11 @@ void OomInterventionImpl::ReportMemoryStats( ...@@ -134,13 +136,11 @@ void OomInterventionImpl::ReportMemoryStats(
"Memory.Experimental.OomIntervention.RendererVmSize", "Memory.Experimental.OomIntervention.RendererVmSize",
base::saturated_cast<base::Histogram::Sample>( base::saturated_cast<base::Histogram::Sample>(
current_memory.current_vm_size_kb / 1024)); current_memory.current_vm_size_kb / 1024));
CrashMemoryMetricsReporterImpl::Instance().WriteIntoSharedMemory(
current_memory);
} }
void OomInterventionImpl::TimerFiredUMAReport(TimerBase*) { void OomInterventionImpl::TimerFiredUMAReport(TimerBase*) {
OomInterventionMetrics current_memory = GetCurrentMemoryMetrics(); OomInterventionMetrics current_memory =
CrashMemoryMetricsReporterImpl::Instance().GetCurrentMemoryMetrics();
switch (number_of_report_needed_--) { switch (number_of_report_needed_--) {
case 3: case 3:
base::UmaHistogramSparse( base::UmaHistogramSparse(
......
...@@ -5,11 +5,10 @@ ...@@ -5,11 +5,10 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CONTROLLER_OOM_INTERVENTION_IMPL_H_ #ifndef THIRD_PARTY_BLINK_RENDERER_CONTROLLER_OOM_INTERVENTION_IMPL_H_
#define THIRD_PARTY_BLINK_RENDERER_CONTROLLER_OOM_INTERVENTION_IMPL_H_ #define THIRD_PARTY_BLINK_RENDERER_CONTROLLER_OOM_INTERVENTION_IMPL_H_
#include "base/files/scoped_file.h"
#include "third_party/blink/public/common/oom_intervention/oom_intervention_types.h" #include "third_party/blink/public/common/oom_intervention/oom_intervention_types.h"
#include "third_party/blink/public/platform/oom_intervention.mojom-blink.h" #include "third_party/blink/public/platform/oom_intervention.mojom-blink.h"
#include "third_party/blink/renderer/controller/controller_export.h" #include "third_party/blink/renderer/controller/controller_export.h"
#include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/controller/memory_usage_monitor.h"
#include "third_party/blink/renderer/core/page/scoped_page_pauser.h" #include "third_party/blink/renderer/core/page/scoped_page_pauser.h"
#include "third_party/blink/renderer/platform/timer.h" #include "third_party/blink/renderer/platform/timer.h"
...@@ -20,7 +19,8 @@ class OomInterventionImplTest; ...@@ -20,7 +19,8 @@ class OomInterventionImplTest;
// Implementation of OOM intervention. This pauses all pages by using // Implementation of OOM intervention. This pauses all pages by using
// ScopedPagePauser when near-OOM situation is detected. // ScopedPagePauser when near-OOM situation is detected.
class CONTROLLER_EXPORT OomInterventionImpl class CONTROLLER_EXPORT OomInterventionImpl
: public mojom::blink::OomIntervention { : public mojom::blink::OomIntervention,
public MemoryUsageMonitor::Observer {
public: public:
static void Create(mojom::blink::OomInterventionRequest); static void Create(mojom::blink::OomInterventionRequest);
...@@ -34,17 +34,20 @@ class CONTROLLER_EXPORT OomInterventionImpl ...@@ -34,17 +34,20 @@ class CONTROLLER_EXPORT OomInterventionImpl
bool navigate_ads_enabled, bool navigate_ads_enabled,
bool purge_v8_memory_enabled) override; bool purge_v8_memory_enabled) override;
// MemoryUsageMonitor::Observer:
void OnMemoryPing(MemoryUsage) override;
private: private:
FRIEND_TEST_ALL_PREFIXES(OomInterventionImplTest, DetectedAndDeclined); FRIEND_TEST_ALL_PREFIXES(OomInterventionImplTest, DetectedAndDeclined);
FRIEND_TEST_ALL_PREFIXES(OomInterventionImplTest, CalculateProcessFootprint);
FRIEND_TEST_ALL_PREFIXES(OomInterventionImplTest, StopWatchingAfterDetection); FRIEND_TEST_ALL_PREFIXES(OomInterventionImplTest, StopWatchingAfterDetection);
FRIEND_TEST_ALL_PREFIXES(OomInterventionImplTest, FRIEND_TEST_ALL_PREFIXES(OomInterventionImplTest,
ContinueWatchingWithoutDetection); ContinueWatchingWithoutDetection);
FRIEND_TEST_ALL_PREFIXES(OomInterventionImplTest, V1DetectionAdsNavigation); FRIEND_TEST_ALL_PREFIXES(OomInterventionImplTest, V1DetectionAdsNavigation);
// Overridden by test. // Overridden by test.
virtual OomInterventionMetrics GetCurrentMemoryMetrics(); virtual MemoryUsageMonitor& MemoryUsageMonitorInstance();
void Check(TimerBase*);
void Check(OomInterventionMetrics);
void ReportMemoryStats(OomInterventionMetrics& current_memory); void ReportMemoryStats(OomInterventionMetrics& current_memory);
...@@ -58,7 +61,6 @@ class CONTROLLER_EXPORT OomInterventionImpl ...@@ -58,7 +61,6 @@ class CONTROLLER_EXPORT OomInterventionImpl
bool renderer_pause_enabled_ = false; bool renderer_pause_enabled_ = false;
bool navigate_ads_enabled_ = false; bool navigate_ads_enabled_ = false;
bool purge_v8_memory_enabled_ = false; bool purge_v8_memory_enabled_ = false;
TaskRunnerTimer<OomInterventionImpl> timer_;
std::unique_ptr<ScopedPagePauser> pauser_; std::unique_ptr<ScopedPagePauser> pauser_;
OomInterventionMetrics metrics_at_intervention_; OomInterventionMetrics metrics_at_intervention_;
int number_of_report_needed_ = 0; int number_of_report_needed_ = 0;
......
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