blob: 7f33f0e3d6d2fc69c2802dcf5edb1280aa1aa707 [file] [log] [blame]
// 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.
#include "third_party/blink/renderer/controller/crash_memory_metrics_reporter_impl.h"
#include "base/allocator/partition_allocator/oom_callback.h"
#include "base/metrics/histogram_macros.h"
#include "base/process/memory.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/controller/memory_usage_monitor_android.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/wtf/allocator/partitions.h"
namespace blink {
// static
void CrashMemoryMetricsReporterImpl::Bind(
mojom::blink::CrashMemoryMetricsReporterRequest request) {
// This should be called only once per process on RenderProcessWillLaunch.
DCHECK(!CrashMemoryMetricsReporterImpl::Instance().binding_.is_bound());
CrashMemoryMetricsReporterImpl::Instance().binding_.Bind(std::move(request));
}
CrashMemoryMetricsReporterImpl& CrashMemoryMetricsReporterImpl::Instance() {
DEFINE_STATIC_LOCAL(CrashMemoryMetricsReporterImpl,
crash_memory_metrics_reporter_impl, ());
return crash_memory_metrics_reporter_impl;
}
CrashMemoryMetricsReporterImpl::CrashMemoryMetricsReporterImpl()
: binding_(this) {
base::SetPartitionAllocOomCallback(
CrashMemoryMetricsReporterImpl::OnOOMCallback);
}
CrashMemoryMetricsReporterImpl::~CrashMemoryMetricsReporterImpl() = default;
void CrashMemoryMetricsReporterImpl::SetSharedMemory(
base::UnsafeSharedMemoryRegion shared_metrics_buffer) {
// This method should be called only once per process.
DCHECK(!shared_metrics_mapping_.IsValid());
shared_metrics_mapping_ = shared_metrics_buffer.Map();
}
void CrashMemoryMetricsReporterImpl::OnMemoryPing(MemoryUsage usage) {
WriteIntoSharedMemory(
CrashMemoryMetricsReporterImpl::MemoryUsageToMetrics(usage));
}
void CrashMemoryMetricsReporterImpl::WriteIntoSharedMemory(
const OomInterventionMetrics& metrics) {
if (!shared_metrics_mapping_.IsValid())
return;
auto* metrics_shared =
shared_metrics_mapping_.GetMemoryAs<OomInterventionMetrics>();
memcpy(metrics_shared, &metrics, sizeof(OomInterventionMetrics));
}
void CrashMemoryMetricsReporterImpl::OnOOMCallback() {
// TODO(yuzus: Support allocation failures on other threads as well.
if (!IsMainThread())
return;
// If shared_metrics_mapping_ is not set, it means OnNoMemory happened before
// initializing render process host sets the shared memory.
if (!CrashMemoryMetricsReporterImpl::Instance()
.shared_metrics_mapping_.IsValid())
return;
// Else, we can send the allocation_failed bool.
OomInterventionMetrics metrics;
// TODO(yuzus): Report this UMA on all the platforms. Currently this is only
// reported on Android.
metrics.allocation_failed = 1; // true
CrashMemoryMetricsReporterImpl::Instance().WriteIntoSharedMemory(metrics);
}
OomInterventionMetrics
CrashMemoryMetricsReporterImpl::GetCurrentMemoryMetrics() {
return MemoryUsageToMetrics(
MemoryUsageMonitor::Instance().GetCurrentMemoryUsage());
}
// static
OomInterventionMetrics CrashMemoryMetricsReporterImpl::MemoryUsageToMetrics(
MemoryUsage usage) {
OomInterventionMetrics metrics = {};
DCHECK(!std::isnan(usage.private_footprint_bytes));
DCHECK(!std::isnan(usage.swap_bytes));
DCHECK(!std::isnan(usage.vm_size_bytes));
metrics.current_blink_usage_kb =
(usage.v8_bytes + usage.blink_gc_bytes + usage.partition_alloc_bytes) /
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
return metrics;
}
} // namespace blink