2014-08-20 10:33:03 +00:00
|
|
|
// Copyright 2014 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.
|
|
|
|
|
|
|
|
#ifndef V8_HEAP_GC_IDLE_TIME_HANDLER_H_
|
|
|
|
#define V8_HEAP_GC_IDLE_TIME_HANDLER_H_
|
|
|
|
|
|
|
|
#include "src/globals.h"
|
|
|
|
|
|
|
|
namespace v8 {
|
|
|
|
namespace internal {
|
|
|
|
|
2014-08-21 14:42:22 +00:00
|
|
|
enum GCIdleTimeActionType {
|
|
|
|
DO_NOTHING,
|
|
|
|
DO_INCREMENTAL_MARKING,
|
|
|
|
DO_SCAVENGE,
|
2014-08-22 11:14:17 +00:00
|
|
|
DO_FULL_GC,
|
|
|
|
DO_FINALIZE_SWEEPING
|
2014-08-21 14:42:22 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class GCIdleTimeAction {
|
|
|
|
public:
|
|
|
|
static GCIdleTimeAction Nothing() {
|
|
|
|
GCIdleTimeAction result;
|
|
|
|
result.type = DO_NOTHING;
|
|
|
|
result.parameter = 0;
|
|
|
|
return result;
|
|
|
|
}
|
2014-08-22 11:14:17 +00:00
|
|
|
|
2014-08-21 14:42:22 +00:00
|
|
|
static GCIdleTimeAction IncrementalMarking(intptr_t step_size) {
|
|
|
|
GCIdleTimeAction result;
|
|
|
|
result.type = DO_INCREMENTAL_MARKING;
|
|
|
|
result.parameter = step_size;
|
|
|
|
return result;
|
|
|
|
}
|
2014-08-22 11:14:17 +00:00
|
|
|
|
2014-08-21 14:42:22 +00:00
|
|
|
static GCIdleTimeAction Scavenge() {
|
|
|
|
GCIdleTimeAction result;
|
|
|
|
result.type = DO_SCAVENGE;
|
|
|
|
result.parameter = 0;
|
|
|
|
return result;
|
|
|
|
}
|
2014-08-22 11:14:17 +00:00
|
|
|
|
2014-08-21 14:42:22 +00:00
|
|
|
static GCIdleTimeAction FullGC() {
|
|
|
|
GCIdleTimeAction result;
|
|
|
|
result.type = DO_FULL_GC;
|
|
|
|
result.parameter = 0;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2014-08-22 11:14:17 +00:00
|
|
|
static GCIdleTimeAction FinalizeSweeping() {
|
|
|
|
GCIdleTimeAction result;
|
|
|
|
result.type = DO_FINALIZE_SWEEPING;
|
|
|
|
result.parameter = 0;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2014-08-21 14:42:22 +00:00
|
|
|
GCIdleTimeActionType type;
|
|
|
|
intptr_t parameter;
|
|
|
|
};
|
|
|
|
|
2014-08-22 09:18:10 +00:00
|
|
|
|
2014-08-21 14:42:22 +00:00
|
|
|
class GCTracer;
|
|
|
|
|
2014-08-20 10:33:03 +00:00
|
|
|
// The idle time handler makes decisions about which garbage collection
|
|
|
|
// operations are executing during IdleNotification.
|
|
|
|
class GCIdleTimeHandler {
|
|
|
|
public:
|
|
|
|
// If we haven't recorded any incremental marking events yet, we carefully
|
|
|
|
// mark with a conservative lower bound for the marking speed.
|
2014-08-20 15:37:43 +00:00
|
|
|
static const size_t kInitialConservativeMarkingSpeed = 100 * KB;
|
|
|
|
|
|
|
|
// Maximum marking step size returned by EstimateMarkingStepSize.
|
|
|
|
static const size_t kMaximumMarkingStepSize = 700 * MB;
|
2014-08-20 10:33:03 +00:00
|
|
|
|
|
|
|
// We have to make sure that we finish the IdleNotification before
|
|
|
|
// idle_time_in_ms. Hence, we conservatively prune our workload estimate.
|
|
|
|
static const double kConservativeTimeRatio;
|
|
|
|
|
2014-08-21 14:42:22 +00:00
|
|
|
// If we haven't recorded any mark-compact events yet, we use
|
|
|
|
// conservative lower bound for the mark-compact speed.
|
|
|
|
static const size_t kInitialConservativeMarkCompactSpeed = 2 * MB;
|
|
|
|
|
|
|
|
// Maximum mark-compact time returned by EstimateMarkCompactTime.
|
2014-08-22 11:14:17 +00:00
|
|
|
static const size_t kMaxMarkCompactTimeInMs = 1000000;
|
|
|
|
|
|
|
|
// Minimum time to finalize sweeping phase. The main thread may wait for
|
|
|
|
// sweeper threads.
|
|
|
|
static const size_t kMinTimeForFinalizeSweeping = 100;
|
2014-08-21 14:42:22 +00:00
|
|
|
|
2014-08-22 09:18:10 +00:00
|
|
|
struct HeapState {
|
|
|
|
int contexts_disposed;
|
|
|
|
size_t size_of_objects;
|
|
|
|
bool incremental_marking_stopped;
|
|
|
|
bool can_start_incremental_marking;
|
2014-08-22 11:14:17 +00:00
|
|
|
bool sweeping_in_progress;
|
2014-08-22 09:18:10 +00:00
|
|
|
};
|
|
|
|
|
2014-08-21 14:42:22 +00:00
|
|
|
GCIdleTimeHandler()
|
|
|
|
: mark_compacts_since_idle_round_started_(0),
|
|
|
|
scavenges_since_last_idle_round_(0) {}
|
|
|
|
|
2014-08-22 11:14:17 +00:00
|
|
|
GCIdleTimeAction Compute(size_t idle_time_in_ms, HeapState heap_state,
|
2014-08-21 14:42:22 +00:00
|
|
|
GCTracer* gc_tracer);
|
|
|
|
|
|
|
|
void NotifyIdleMarkCompact() {
|
|
|
|
if (mark_compacts_since_idle_round_started_ < kMaxMarkCompactsInIdleRound) {
|
|
|
|
++mark_compacts_since_idle_round_started_;
|
|
|
|
if (mark_compacts_since_idle_round_started_ ==
|
|
|
|
kMaxMarkCompactsInIdleRound) {
|
|
|
|
scavenges_since_last_idle_round_ = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void NotifyScavenge() { ++scavenges_since_last_idle_round_; }
|
|
|
|
|
|
|
|
static size_t EstimateMarkingStepSize(size_t idle_time_in_ms,
|
|
|
|
size_t marking_speed_in_bytes_per_ms);
|
|
|
|
|
|
|
|
static size_t EstimateMarkCompactTime(
|
|
|
|
size_t size_of_objects, size_t mark_compact_speed_in_bytes_per_ms);
|
|
|
|
|
2014-08-20 10:33:03 +00:00
|
|
|
private:
|
2014-08-21 14:42:22 +00:00
|
|
|
void StartIdleRound() { mark_compacts_since_idle_round_started_ = 0; }
|
|
|
|
bool IsIdleRoundFinished() {
|
|
|
|
return mark_compacts_since_idle_round_started_ ==
|
|
|
|
kMaxMarkCompactsInIdleRound;
|
|
|
|
}
|
|
|
|
bool EnoughGarbageSinceLastIdleRound() {
|
|
|
|
return scavenges_since_last_idle_round_ >= kIdleScavengeThreshold;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const int kMaxMarkCompactsInIdleRound = 7;
|
|
|
|
static const int kIdleScavengeThreshold = 5;
|
|
|
|
int mark_compacts_since_idle_round_started_;
|
|
|
|
int scavenges_since_last_idle_round_;
|
|
|
|
|
2014-08-20 10:33:03 +00:00
|
|
|
DISALLOW_COPY_AND_ASSIGN(GCIdleTimeHandler);
|
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace internal
|
|
|
|
} // namespace v8
|
|
|
|
|
|
|
|
#endif // V8_HEAP_GC_IDLE_TIME_HANDLER_H_
|