Skip to content

Commit ced669d

Browse files
mlippautzCommit Bot
authored andcommitted
heap: Remove context disposal GCs
Full GCs on non-main-frame context disposals show up on real-world web workloads and often cause missed frames. Remove and let the regular scheduler take over these workloads. Bug: chromium:1191325 Change-Id: Ib58419e4623c096321860db05c36ddf9c8e9f4e4 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2773347 Commit-Queue: Michael Lippautz <[email protected]> Reviewed-by: Ulan Degenbaev <[email protected]> Cr-Commit-Position: refs/heads/master@{#73799}
1 parent b19385f commit ced669d

File tree

7 files changed

+3
-159
lines changed

7 files changed

+3
-159
lines changed

src/heap/gc-idle-time-handler.cc

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,8 @@ namespace v8 {
1212
namespace internal {
1313

1414
const double GCIdleTimeHandler::kConservativeTimeRatio = 0.9;
15-
const double GCIdleTimeHandler::kHighContextDisposalRate = 100;
1615

1716
void GCIdleTimeHeapState::Print() {
18-
PrintF("contexts_disposed=%d ", contexts_disposed);
19-
PrintF("contexts_disposal_rate=%f ", contexts_disposal_rate);
2017
PrintF("size_of_objects=%zu ", size_of_objects);
2118
PrintF("incremental_marking_stopped=%d ", incremental_marking_stopped);
2219
}
@@ -36,14 +33,6 @@ size_t GCIdleTimeHandler::EstimateMarkingStepSize(
3633
return static_cast<size_t>(marking_step_size * kConservativeTimeRatio);
3734
}
3835

39-
bool GCIdleTimeHandler::ShouldDoContextDisposalMarkCompact(
40-
int contexts_disposed, double contexts_disposal_rate,
41-
size_t size_of_objects) {
42-
return contexts_disposed > 0 && contexts_disposal_rate > 0 &&
43-
contexts_disposal_rate < kHighContextDisposalRate &&
44-
size_of_objects <= kMaxHeapSizeForContextDisposalMarkCompact;
45-
}
46-
4736
// The following logic is implemented by the controller:
4837
// (1) If we don't have any idle time, do nothing, unless a context was
4938
// disposed, incremental marking is stopped, and the heap is small. Then do
@@ -54,13 +43,6 @@ bool GCIdleTimeHandler::ShouldDoContextDisposalMarkCompact(
5443
GCIdleTimeAction GCIdleTimeHandler::Compute(double idle_time_in_ms,
5544
GCIdleTimeHeapState heap_state) {
5645
if (static_cast<int>(idle_time_in_ms) <= 0) {
57-
if (heap_state.incremental_marking_stopped) {
58-
if (ShouldDoContextDisposalMarkCompact(heap_state.contexts_disposed,
59-
heap_state.contexts_disposal_rate,
60-
heap_state.size_of_objects)) {
61-
return GCIdleTimeAction::kFullGC;
62-
}
63-
}
6446
return GCIdleTimeAction::kDone;
6547
}
6648

src/heap/gc-idle-time-handler.h

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,12 @@ namespace internal {
1313
enum class GCIdleTimeAction : uint8_t {
1414
kDone,
1515
kIncrementalStep,
16-
kFullGC,
1716
};
1817

1918
class GCIdleTimeHeapState {
2019
public:
2120
void Print();
2221

23-
int contexts_disposed;
24-
double contexts_disposal_rate;
2522
size_t size_of_objects;
2623
bool incremental_marking_stopped;
2724
};
@@ -46,11 +43,6 @@ class V8_EXPORT_PRIVATE GCIdleTimeHandler {
4643
// 16.66 ms when there is currently no rendering going on.
4744
static const size_t kMaxScheduledIdleTime = 50;
4845

49-
static const size_t kMaxHeapSizeForContextDisposalMarkCompact = 100 * MB;
50-
51-
// If contexts are disposed at a higher rate a full gc is triggered.
52-
static const double kHighContextDisposalRate;
53-
5446
GCIdleTimeHandler() = default;
5547
GCIdleTimeHandler(const GCIdleTimeHandler&) = delete;
5648
GCIdleTimeHandler& operator=(const GCIdleTimeHandler&) = delete;
@@ -65,10 +57,6 @@ class V8_EXPORT_PRIVATE GCIdleTimeHandler {
6557

6658
static double EstimateFinalIncrementalMarkCompactTime(
6759
size_t size_of_objects, double mark_compact_speed_in_bytes_per_ms);
68-
69-
static bool ShouldDoContextDisposalMarkCompact(int context_disposed,
70-
double contexts_disposal_rate,
71-
size_t size_of_objects);
7260
};
7361

7462
} // namespace internal

src/heap/gc-tracer.cc

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,6 @@ void GCTracer::ResetForTesting() {
208208
recorded_new_generation_allocations_.Reset();
209209
recorded_old_generation_allocations_.Reset();
210210
recorded_embedder_generation_allocations_.Reset();
211-
recorded_context_disposal_times_.Reset();
212211
recorded_survival_ratios_.Reset();
213212
start_counter_ = 0;
214213
average_mutator_duration_ = 0;
@@ -472,11 +471,6 @@ void GCTracer::AddAllocation(double current_ms) {
472471
embedder_allocation_in_bytes_since_gc_ = 0;
473472
}
474473

475-
476-
void GCTracer::AddContextDisposalTime(double time) {
477-
recorded_context_disposal_times_.Push(time);
478-
}
479-
480474
void GCTracer::AddCompactionEvent(double duration,
481475
size_t live_bytes_compacted) {
482476
recorded_compactions_.Push(
@@ -612,8 +606,7 @@ void GCTracer::PrintNVP() const {
612606
"promotion_rate=%.1f%% "
613607
"semi_space_copy_rate=%.1f%% "
614608
"new_space_allocation_throughput=%.1f "
615-
"unmapper_chunks=%d "
616-
"context_disposal_rate=%.1f\n",
609+
"unmapper_chunks=%d\n",
617610
duration, spent_in_mutator, current_.TypeName(true),
618611
current_.reduce_memory, current_.scopes[Scope::TIME_TO_SAFEPOINT],
619612
current_.scopes[Scope::HEAP_PROLOGUE],
@@ -651,8 +644,7 @@ void GCTracer::PrintNVP() const {
651644
AverageSurvivalRatio(), heap_->promotion_rate_,
652645
heap_->semi_space_copied_rate_,
653646
NewSpaceAllocationThroughputInBytesPerMillisecond(),
654-
heap_->memory_allocator()->unmapper()->NumberOfChunks(),
655-
ContextDisposalRateInMilliseconds());
647+
heap_->memory_allocator()->unmapper()->NumberOfChunks());
656648
break;
657649
case Event::MINOR_MARK_COMPACTOR:
658650
heap_->isolate()->PrintWithTimestamp(
@@ -804,7 +796,6 @@ void GCTracer::PrintNVP() const {
804796
"semi_space_copy_rate=%.1f%% "
805797
"new_space_allocation_throughput=%.1f "
806798
"unmapper_chunks=%d "
807-
"context_disposal_rate=%.1f "
808799
"compaction_speed=%.f\n",
809800
duration, spent_in_mutator, current_.TypeName(true),
810801
current_.reduce_memory, current_.scopes[Scope::TIME_TO_SAFEPOINT],
@@ -896,7 +887,6 @@ void GCTracer::PrintNVP() const {
896887
heap_->semi_space_copied_rate_,
897888
NewSpaceAllocationThroughputInBytesPerMillisecond(),
898889
heap_->memory_allocator()->unmapper()->NumberOfChunks(),
899-
ContextDisposalRateInMilliseconds(),
900890
CompactionSpeedInBytesPerMillisecond());
901891
break;
902892
case Event::START:
@@ -1118,16 +1108,6 @@ double GCTracer::CurrentEmbedderAllocationThroughputInBytesPerMillisecond()
11181108
kThroughputTimeFrameMs);
11191109
}
11201110

1121-
double GCTracer::ContextDisposalRateInMilliseconds() const {
1122-
if (recorded_context_disposal_times_.Count() <
1123-
recorded_context_disposal_times_.kSize)
1124-
return 0.0;
1125-
double begin = heap_->MonotonicallyIncreasingTimeInMs();
1126-
double end = recorded_context_disposal_times_.Sum(
1127-
[](double a, double b) { return b; }, 0.0);
1128-
return (begin - end) / recorded_context_disposal_times_.Count();
1129-
}
1130-
11311111
double GCTracer::AverageSurvivalRatio() const {
11321112
if (recorded_survival_ratios_.Count() == 0) return 0.0;
11331113
double sum = recorded_survival_ratios_.Sum(

src/heap/gc-tracer.h

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -221,8 +221,6 @@ class V8_EXPORT_PRIVATE GCTracer {
221221
// Log the accumulated new space allocation bytes.
222222
void AddAllocation(double current_ms);
223223

224-
void AddContextDisposalTime(double time);
225-
226224
void AddCompactionEvent(double duration, size_t live_bytes_compacted);
227225

228226
void AddSurvivalRatio(double survival_ratio);
@@ -297,12 +295,6 @@ class V8_EXPORT_PRIVATE GCTracer {
297295
// Returns 0 if no allocation events have been recorded.
298296
double CurrentEmbedderAllocationThroughputInBytesPerMillisecond() const;
299297

300-
// Computes the context disposal rate in milliseconds. It takes the time
301-
// frame of the first recorded context disposal to the current time and
302-
// divides it by the number of recorded events.
303-
// Returns 0 if no events have been recorded.
304-
double ContextDisposalRateInMilliseconds() const;
305-
306298
// Computes the average survival ratio based on the last recorded survival
307299
// events.
308300
// Returns 0 if no events have been recorded.
@@ -479,7 +471,6 @@ class V8_EXPORT_PRIVATE GCTracer {
479471
base::RingBuffer<BytesAndDuration> recorded_new_generation_allocations_;
480472
base::RingBuffer<BytesAndDuration> recorded_old_generation_allocations_;
481473
base::RingBuffer<BytesAndDuration> recorded_embedder_generation_allocations_;
482-
base::RingBuffer<double> recorded_context_disposal_times_;
483474
base::RingBuffer<double> recorded_survival_ratios_;
484475

485476
base::Mutex background_counter_mutex_;

src/heap/heap.cc

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1750,8 +1750,6 @@ int Heap::NotifyContextDisposed(bool dependant_context) {
17501750
isolate()->raw_native_context().set_retained_maps(
17511751
ReadOnlyRoots(this).empty_weak_array_list());
17521752
}
1753-
1754-
tracer()->AddContextDisposalTime(MonotonicallyIncreasingTimeInMs());
17551753
return ++contexts_disposed_;
17561754
}
17571755

@@ -2252,6 +2250,7 @@ void Heap::MarkCompact() {
22522250
mark_compact_collector()->Prepare();
22532251

22542252
ms_count_++;
2253+
contexts_disposed_ = 0;
22552254

22562255
MarkCompactPrologue();
22572256

@@ -3623,9 +3622,6 @@ void Heap::VerifyObjectLayoutChange(HeapObject object, Map new_map) {
36233622

36243623
GCIdleTimeHeapState Heap::ComputeHeapState() {
36253624
GCIdleTimeHeapState heap_state;
3626-
heap_state.contexts_disposed = contexts_disposed_;
3627-
heap_state.contexts_disposal_rate =
3628-
tracer()->ContextDisposalRateInMilliseconds();
36293625
heap_state.size_of_objects = static_cast<size_t>(SizeOfObjects());
36303626
heap_state.incremental_marking_stopped = incremental_marking()->IsStopped();
36313627
return heap_state;
@@ -3648,13 +3644,6 @@ bool Heap::PerformIdleTimeAction(GCIdleTimeAction action,
36483644
result = incremental_marking()->IsStopped();
36493645
break;
36503646
}
3651-
case GCIdleTimeAction::kFullGC: {
3652-
DCHECK_LT(0, contexts_disposed_);
3653-
HistogramTimerScope scope(isolate_->counters()->gc_context());
3654-
TRACE_EVENT0("v8", "V8.GCContext");
3655-
CollectAllGarbage(kNoGCFlags, GarbageCollectionReason::kContextDisposal);
3656-
break;
3657-
}
36583647
}
36593648

36603649
return result;
@@ -3668,8 +3657,6 @@ void Heap::IdleNotificationEpilogue(GCIdleTimeAction action,
36683657
last_idle_notification_time_ = current_time;
36693658
double deadline_difference = deadline_in_ms - current_time;
36703659

3671-
contexts_disposed_ = 0;
3672-
36733660
if (FLAG_trace_idle_notification) {
36743661
isolate_->PrintWithTimestamp(
36753662
"Idle notification: requested idle time %.2f ms, used idle time %.2f "
@@ -3683,9 +3670,6 @@ void Heap::IdleNotificationEpilogue(GCIdleTimeAction action,
36833670
case GCIdleTimeAction::kIncrementalStep:
36843671
PrintF("incremental step");
36853672
break;
3686-
case GCIdleTimeAction::kFullGC:
3687-
PrintF("full GC");
3688-
break;
36893673
}
36903674
PrintF("]");
36913675
if (FLAG_trace_idle_notification_verbose) {
@@ -3727,12 +3711,9 @@ bool Heap::IdleNotification(double deadline_in_seconds) {
37273711
EmbedderAllocationCounter());
37283712

37293713
GCIdleTimeHeapState heap_state = ComputeHeapState();
3730-
37313714
GCIdleTimeAction action =
37323715
gc_idle_time_handler_->Compute(idle_time_in_ms, heap_state);
3733-
37343716
bool result = PerformIdleTimeAction(action, heap_state, deadline_in_ms);
3735-
37363717
IdleNotificationEpilogue(action, heap_state, start_ms, deadline_in_ms);
37373718
return result;
37383719
}

src/logging/counters-definitions.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,6 @@ namespace internal {
100100
#define HISTOGRAM_TIMER_LIST(HT) \
101101
/* Timer histograms, not thread safe: HT(name, caption, max, unit) */ \
102102
/* Garbage collection timers. */ \
103-
HT(gc_context, V8.GCContext, 10000, \
104-
MILLISECOND) /* GC context cleanup time */ \
105103
HT(gc_idle_notification, V8.GCIdleNotification, 10000, MILLISECOND) \
106104
HT(gc_incremental_marking, V8.GCIncrementalMarking, 10000, MILLISECOND) \
107105
HT(gc_incremental_marking_start, V8.GCIncrementalMarkingStart, 10000, \

test/unittests/heap/gc-idle-time-handler-unittest.cc

Lines changed: 0 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@ class GCIdleTimeHandlerTest : public ::testing::Test {
2121

2222
GCIdleTimeHeapState DefaultHeapState() {
2323
GCIdleTimeHeapState result;
24-
result.contexts_disposed = 0;
25-
result.contexts_disposal_rate = GCIdleTimeHandler::kHighContextDisposalRate;
2624
result.incremental_marking_stopped = false;
2725
result.size_of_objects = kSizeOfObjects;
2826
return result;
@@ -72,80 +70,6 @@ TEST(GCIdleTimeHandler, EstimateMarkingStepSizeOverflow2) {
7270
step_size);
7371
}
7472

75-
76-
TEST_F(GCIdleTimeHandlerTest, ContextDisposeLowRate) {
77-
if (!handler()->Enabled()) return;
78-
GCIdleTimeHeapState heap_state = DefaultHeapState();
79-
heap_state.contexts_disposed = 1;
80-
heap_state.incremental_marking_stopped = true;
81-
double idle_time_ms = 0;
82-
EXPECT_EQ(GCIdleTimeAction::kDone,
83-
handler()->Compute(idle_time_ms, heap_state));
84-
}
85-
86-
87-
TEST_F(GCIdleTimeHandlerTest, ContextDisposeHighRate) {
88-
if (!handler()->Enabled()) return;
89-
GCIdleTimeHeapState heap_state = DefaultHeapState();
90-
heap_state.contexts_disposed = 1;
91-
heap_state.contexts_disposal_rate =
92-
GCIdleTimeHandler::kHighContextDisposalRate - 1;
93-
heap_state.incremental_marking_stopped = true;
94-
double idle_time_ms = 0;
95-
EXPECT_EQ(GCIdleTimeAction::kFullGC,
96-
handler()->Compute(idle_time_ms, heap_state));
97-
}
98-
99-
100-
TEST_F(GCIdleTimeHandlerTest, AfterContextDisposeZeroIdleTime) {
101-
if (!handler()->Enabled()) return;
102-
GCIdleTimeHeapState heap_state = DefaultHeapState();
103-
heap_state.contexts_disposed = 1;
104-
heap_state.contexts_disposal_rate = 1.0;
105-
heap_state.incremental_marking_stopped = true;
106-
double idle_time_ms = 0;
107-
EXPECT_EQ(GCIdleTimeAction::kFullGC,
108-
handler()->Compute(idle_time_ms, heap_state));
109-
}
110-
111-
112-
TEST_F(GCIdleTimeHandlerTest, AfterContextDisposeSmallIdleTime1) {
113-
if (!handler()->Enabled()) return;
114-
GCIdleTimeHeapState heap_state = DefaultHeapState();
115-
heap_state.contexts_disposed = 1;
116-
heap_state.contexts_disposal_rate =
117-
GCIdleTimeHandler::kHighContextDisposalRate;
118-
size_t speed = kMarkCompactSpeed;
119-
double idle_time_ms = static_cast<double>(kSizeOfObjects / speed - 1);
120-
EXPECT_EQ(GCIdleTimeAction::kIncrementalStep,
121-
handler()->Compute(idle_time_ms, heap_state));
122-
}
123-
124-
125-
TEST_F(GCIdleTimeHandlerTest, AfterContextDisposeSmallIdleTime2) {
126-
if (!handler()->Enabled()) return;
127-
GCIdleTimeHeapState heap_state = DefaultHeapState();
128-
heap_state.contexts_disposed = 1;
129-
heap_state.contexts_disposal_rate =
130-
GCIdleTimeHandler::kHighContextDisposalRate;
131-
size_t speed = kMarkCompactSpeed;
132-
double idle_time_ms = static_cast<double>(kSizeOfObjects / speed - 1);
133-
EXPECT_EQ(GCIdleTimeAction::kIncrementalStep,
134-
handler()->Compute(idle_time_ms, heap_state));
135-
}
136-
137-
TEST_F(GCIdleTimeHandlerTest, AfterContextDisposeLargeHeap) {
138-
if (!handler()->Enabled()) return;
139-
GCIdleTimeHeapState heap_state = DefaultHeapState();
140-
heap_state.contexts_disposed = 1;
141-
heap_state.contexts_disposal_rate = 1.0;
142-
heap_state.incremental_marking_stopped = true;
143-
heap_state.size_of_objects = 101 * MB;
144-
double idle_time_ms = 0;
145-
EXPECT_EQ(GCIdleTimeAction::kDone,
146-
handler()->Compute(idle_time_ms, heap_state));
147-
}
148-
14973
TEST_F(GCIdleTimeHandlerTest, IncrementalMarking1) {
15074
if (!handler()->Enabled()) return;
15175
GCIdleTimeHeapState heap_state = DefaultHeapState();

0 commit comments

Comments
 (0)