%PDF- %PDF-
| Direktori : /home/vacivi36/vittasync.vacivitta.com.br/vittasync/node/deps/v8/src/heap/ |
| Current File : /home/vacivi36/vittasync.vacivitta.com.br/vittasync/node/deps/v8/src/heap/memory-balancer.cc |
// Copyright 2023 the V8 project 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 "src/heap/memory-balancer.h"
#include "src/heap/heap-inl.h"
#include "src/heap/heap.h"
namespace v8 {
namespace internal {
MemoryBalancer::MemoryBalancer(Heap* heap, base::TimeTicks startup_time)
: heap_(heap), last_measured_at_(startup_time) {}
void MemoryBalancer::RecomputeLimits(size_t embedder_allocation_limit,
base::TimeTicks time) {
embedder_allocation_limit_ = embedder_allocation_limit;
last_measured_memory_ = live_memory_after_gc_ =
heap_->OldGenerationSizeOfObjects();
last_measured_at_ = time;
RefreshLimit();
PostHeartbeatTask();
}
void MemoryBalancer::RefreshLimit() {
CHECK(major_allocation_rate_.has_value());
CHECK(major_gc_speed_.has_value());
const size_t computed_limit =
live_memory_after_gc_ +
sqrt(live_memory_after_gc_ * (major_allocation_rate_.value().rate()) /
(major_gc_speed_.value().rate()) / v8_flags.memory_balancer_c_value);
// 2 MB of extra space.
// This allows the heap size to not decay to CurrentSizeOfObject()
// and prevents GC from triggering if, after a long period of idleness,
// a small allocation appears.
constexpr size_t kMinHeapExtraSpace = 2 * MB;
const size_t minimum_limit = live_memory_after_gc_ + kMinHeapExtraSpace;
size_t new_limit = std::max<size_t>(minimum_limit, computed_limit);
new_limit = std::min<size_t>(new_limit, heap_->max_old_generation_size());
new_limit = std::max<size_t>(new_limit, heap_->min_old_generation_size());
if (v8_flags.trace_memory_balancer) {
heap_->isolate()->PrintWithTimestamp(
"MemoryBalancer: allocation-rate=%.1lfKB/ms gc-speed=%.1lfKB/ms "
"minium-limit=%.1lfM computed-limit=%.1lfM new-limit=%.1lfM\n",
major_allocation_rate_.value().rate() / KB,
major_gc_speed_.value().rate() / KB,
static_cast<double>(minimum_limit) / MB,
static_cast<double>(computed_limit) / MB,
static_cast<double>(new_limit) / MB);
}
heap_->SetOldGenerationAndGlobalAllocationLimit(
new_limit, new_limit + embedder_allocation_limit_);
}
void MemoryBalancer::UpdateGCSpeed(size_t major_gc_bytes,
base::TimeDelta major_gc_duration) {
if (!major_gc_speed_) {
major_gc_speed_ = SmoothedBytesAndDuration{
major_gc_bytes, major_gc_duration.InMillisecondsF()};
} else {
major_gc_speed_->Update(major_gc_bytes, major_gc_duration.InMillisecondsF(),
kMajorGCDecayRate);
}
}
void MemoryBalancer::UpdateAllocationRate(
size_t major_allocation_bytes, base::TimeDelta major_allocation_duration) {
if (!major_allocation_rate_) {
major_allocation_rate_ = SmoothedBytesAndDuration{
major_allocation_bytes, major_allocation_duration.InMillisecondsF()};
} else {
major_allocation_rate_->Update(major_allocation_bytes,
major_allocation_duration.InMillisecondsF(),
kMajorAllocationDecayRate);
}
}
void MemoryBalancer::HeartbeatUpdate() {
heartbeat_task_started_ = false;
auto time = base::TimeTicks::Now();
auto memory = heap_->OldGenerationSizeOfObjects();
const base::TimeDelta duration = time - last_measured_at_;
const size_t allocated_bytes =
memory > last_measured_memory_ ? memory - last_measured_memory_ : 0;
UpdateAllocationRate(allocated_bytes, duration);
last_measured_memory_ = memory;
last_measured_at_ = time;
RefreshLimit();
PostHeartbeatTask();
}
void MemoryBalancer::PostHeartbeatTask() {
if (heartbeat_task_started_) return;
heartbeat_task_started_ = true;
heap_->GetForegroundTaskRunner()->PostDelayedTask(
std::make_unique<HeartbeatTask>(heap_->isolate(), this), 1);
}
HeartbeatTask::HeartbeatTask(Isolate* isolate, MemoryBalancer* mb)
: CancelableTask(isolate), mb_(mb) {}
void HeartbeatTask::RunInternal() { mb_->HeartbeatUpdate(); }
} // namespace internal
} // namespace v8