blob: 2e153413626a10bbf1aef921c8abac2d0e028a43 [file] [log] [blame]
// Copyright 2017 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 "controller/OomInterventionImpl.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "platform/WebTaskRunner.h"
#include "platform/bindings/V8PerIsolateData.h"
#include "platform/heap/Handle.h"
#include "platform/wtf/allocator/Partitions.h"
#include "public/platform/Platform.h"
namespace blink {
namespace {
// Roughly caclculates amount of memory which is used to execute pages.
size_t BlinkMemoryWorkloadCaculator() {
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
// If memory workload is above this threshold, we assume that we are in a
// near-OOM situation.
const size_t OomInterventionImpl::kMemoryWorkloadThreshold = 80 * 1024 * 1024;
// static
void OomInterventionImpl::Create(mojom::blink::OomInterventionRequest request) {
mojo::MakeStrongBinding(
std::make_unique<OomInterventionImpl>(
WTF::BindRepeating(&BlinkMemoryWorkloadCaculator)),
std::move(request));
}
OomInterventionImpl::OomInterventionImpl(
MemoryWorkloadCaculator workload_calculator)
: workload_calculator_(std::move(workload_calculator)),
timer_(this, &OomInterventionImpl::Check) {
DCHECK(workload_calculator_);
}
OomInterventionImpl::~OomInterventionImpl() = default;
void OomInterventionImpl::StartDetection(
mojom::blink::OomInterventionHostPtr host,
bool trigger_intervention) {
host_ = std::move(host);
trigger_intervention_ = trigger_intervention;
timer_.Start(TimeDelta(), TimeDelta::FromSeconds(1), FROM_HERE);
}
void OomInterventionImpl::Check(TimerBase*) {
DCHECK(host_);
size_t workload = workload_calculator_.Run();
if (workload > kMemoryWorkloadThreshold) {
host_->OnHighMemoryUsage(trigger_intervention_);
if (trigger_intervention_) {
// The ScopedPagePauser is destroyed when the intervention is declined and
// mojo strong binding is disconnected.
pauser_.reset(new ScopedPagePauser);
}
}
}
} // namespace blink