Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(162)

Side by Side Diff: src/heap/heap.cc

Issue 1175663002: Bring back high promotion mode to shrink young generation size when scavenging latency is high. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/heap/heap.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/v8.h" 5 #include "src/v8.h"
6 6
7 #include "src/accessors.h" 7 #include "src/accessors.h"
8 #include "src/api.h" 8 #include "src/api.h"
9 #include "src/base/bits.h" 9 #include "src/base/bits.h"
10 #include "src/base/once.h" 10 #include "src/base/once.h"
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
109 old_generation_allocation_limit_(initial_old_generation_size_), 109 old_generation_allocation_limit_(initial_old_generation_size_),
110 idle_old_generation_allocation_limit_( 110 idle_old_generation_allocation_limit_(
111 kMinimumOldGenerationAllocationLimit), 111 kMinimumOldGenerationAllocationLimit),
112 old_gen_exhausted_(false), 112 old_gen_exhausted_(false),
113 inline_allocation_disabled_(false), 113 inline_allocation_disabled_(false),
114 store_buffer_rebuilder_(store_buffer()), 114 store_buffer_rebuilder_(store_buffer()),
115 hidden_string_(NULL), 115 hidden_string_(NULL),
116 gc_safe_size_of_old_object_(NULL), 116 gc_safe_size_of_old_object_(NULL),
117 total_regexp_code_generated_(0), 117 total_regexp_code_generated_(0),
118 tracer_(this), 118 tracer_(this),
119 new_space_high_promotion_mode_active_(false),
119 high_survival_rate_period_length_(0), 120 high_survival_rate_period_length_(0),
120 promoted_objects_size_(0), 121 promoted_objects_size_(0),
122 low_survival_rate_period_length_(0),
123 survival_rate_(0),
121 promotion_ratio_(0), 124 promotion_ratio_(0),
122 semi_space_copied_object_size_(0), 125 semi_space_copied_object_size_(0),
123 previous_semi_space_copied_object_size_(0), 126 previous_semi_space_copied_object_size_(0),
124 semi_space_copied_rate_(0), 127 semi_space_copied_rate_(0),
125 nodes_died_in_new_space_(0), 128 nodes_died_in_new_space_(0),
126 nodes_copied_in_new_space_(0), 129 nodes_copied_in_new_space_(0),
127 nodes_promoted_(0), 130 nodes_promoted_(0),
128 maximum_size_scavenges_(0), 131 maximum_size_scavenges_(0),
132 previous_survival_rate_trend_(Heap::STABLE),
133 survival_rate_trend_(Heap::STABLE),
129 max_gc_pause_(0.0), 134 max_gc_pause_(0.0),
130 total_gc_time_ms_(0.0), 135 total_gc_time_ms_(0.0),
131 max_alive_after_gc_(0), 136 max_alive_after_gc_(0),
132 min_in_mutator_(kMaxInt), 137 min_in_mutator_(kMaxInt),
133 marking_time_(0.0), 138 marking_time_(0.0),
134 sweeping_time_(0.0), 139 sweeping_time_(0.0),
135 last_idle_notification_time_(0.0), 140 last_idle_notification_time_(0.0),
136 last_gc_time_(0.0), 141 last_gc_time_(0.0),
137 mark_compact_collector_(this), 142 mark_compact_collector_(this),
138 store_buffer_(this), 143 store_buffer_(this),
(...skipping 1026 matching lines...) Expand 10 before | Expand all | Expand 10 after
1165 (static_cast<double>(semi_space_copied_object_size_) / 1170 (static_cast<double>(semi_space_copied_object_size_) /
1166 static_cast<double>(start_new_space_size) * 100); 1171 static_cast<double>(start_new_space_size) * 100);
1167 1172
1168 double survival_rate = promotion_ratio_ + semi_space_copied_rate_; 1173 double survival_rate = promotion_ratio_ + semi_space_copied_rate_;
1169 tracer()->AddSurvivalRatio(survival_rate); 1174 tracer()->AddSurvivalRatio(survival_rate);
1170 if (survival_rate > kYoungSurvivalRateHighThreshold) { 1175 if (survival_rate > kYoungSurvivalRateHighThreshold) {
1171 high_survival_rate_period_length_++; 1176 high_survival_rate_period_length_++;
1172 } else { 1177 } else {
1173 high_survival_rate_period_length_ = 0; 1178 high_survival_rate_period_length_ = 0;
1174 } 1179 }
1180
1181 if (survival_rate < kYoungSurvivalRateLowThreshold) {
1182 low_survival_rate_period_length_++;
1183 } else {
1184 low_survival_rate_period_length_ = 0;
1185 }
1186
1187 double survival_rate_diff = survival_rate_ - survival_rate;
1188
1189 if (survival_rate_diff > kYoungSurvivalRateAllowedDeviation) {
1190 set_survival_rate_trend(DECREASING);
1191 } else if (survival_rate_diff < -kYoungSurvivalRateAllowedDeviation) {
1192 set_survival_rate_trend(INCREASING);
1193 } else {
1194 set_survival_rate_trend(STABLE);
1195 }
1196
1197 survival_rate_ = survival_rate;
1175 } 1198 }
1176 1199
1177 bool Heap::PerformGarbageCollection( 1200 bool Heap::PerformGarbageCollection(
1178 GarbageCollector collector, const v8::GCCallbackFlags gc_callback_flags) { 1201 GarbageCollector collector, const v8::GCCallbackFlags gc_callback_flags) {
1179 int freed_global_handles = 0; 1202 int freed_global_handles = 0;
1180 1203
1181 if (collector != SCAVENGER) { 1204 if (collector != SCAVENGER) {
1182 PROFILE(isolate_, CodeMovingGCEvent()); 1205 PROFILE(isolate_, CodeMovingGCEvent());
1183 } 1206 }
1184 1207
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
1221 old_generation_size_configured_ = true; 1244 old_generation_size_configured_ = true;
1222 } else { 1245 } else {
1223 Scavenge(); 1246 Scavenge();
1224 } 1247 }
1225 1248
1226 // This should be updated before PostGarbageCollectionProcessing, which can 1249 // This should be updated before PostGarbageCollectionProcessing, which can
1227 // cause another GC. 1250 // cause another GC.
1228 old_generation_size_at_last_gc_ = PromotedSpaceSizeOfObjects(); 1251 old_generation_size_at_last_gc_ = PromotedSpaceSizeOfObjects();
1229 1252
1230 UpdateSurvivalStatistics(start_new_space_size); 1253 UpdateSurvivalStatistics(start_new_space_size);
1254 ConfigureNewGenerationSize();
1231 ConfigureInitialOldGenerationSize(); 1255 ConfigureInitialOldGenerationSize();
1232 1256
1233 isolate_->counters()->objs_since_last_young()->Set(0); 1257 isolate_->counters()->objs_since_last_young()->Set(0);
1234 1258
1235 if (collector != SCAVENGER) { 1259 if (collector != SCAVENGER) {
1236 // Callbacks that fire after this point might trigger nested GCs and 1260 // Callbacks that fire after this point might trigger nested GCs and
1237 // restart incremental marking, the assertion can't be moved down. 1261 // restart incremental marking, the assertion can't be moved down.
1238 DCHECK(incremental_marking()->IsStopped()); 1262 DCHECK(incremental_marking()->IsStopped());
1239 1263
1240 // We finished a marking cycle. We can uncommit the marking deque until 1264 // We finished a marking cycle. We can uncommit the marking deque until
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after
1438 void Heap::CheckNewSpaceExpansionCriteria() { 1462 void Heap::CheckNewSpaceExpansionCriteria() {
1439 if (FLAG_experimental_new_space_growth_heuristic) { 1463 if (FLAG_experimental_new_space_growth_heuristic) {
1440 if (new_space_.TotalCapacity() < new_space_.MaximumCapacity() && 1464 if (new_space_.TotalCapacity() < new_space_.MaximumCapacity() &&
1441 survived_last_scavenge_ * 100 / new_space_.TotalCapacity() >= 10) { 1465 survived_last_scavenge_ * 100 / new_space_.TotalCapacity() >= 10) {
1442 // Grow the size of new space if there is room to grow, and more than 10% 1466 // Grow the size of new space if there is room to grow, and more than 10%
1443 // have survived the last scavenge. 1467 // have survived the last scavenge.
1444 new_space_.Grow(); 1468 new_space_.Grow();
1445 survived_since_last_expansion_ = 0; 1469 survived_since_last_expansion_ = 0;
1446 } 1470 }
1447 } else if (new_space_.TotalCapacity() < new_space_.MaximumCapacity() && 1471 } else if (new_space_.TotalCapacity() < new_space_.MaximumCapacity() &&
1448 survived_since_last_expansion_ > new_space_.TotalCapacity()) { 1472 survived_since_last_expansion_ > new_space_.TotalCapacity() &&
1473 !new_space_high_promotion_mode_active_) {
1449 // Grow the size of new space if there is room to grow, and enough data 1474 // Grow the size of new space if there is room to grow, and enough data
1450 // has survived scavenge since the last expansion. 1475 // has survived scavenge since the last expansion.
1451 new_space_.Grow(); 1476 new_space_.Grow();
1452 survived_since_last_expansion_ = 0; 1477 survived_since_last_expansion_ = 0;
1453 } 1478 }
1454 } 1479 }
1455 1480
1456 1481
1457 static bool IsUnscavengedHeapObject(Heap* heap, Object** p) { 1482 static bool IsUnscavengedHeapObject(Heap* heap, Object** p) {
1458 return heap->InNewSpace(*p) && 1483 return heap->InNewSpace(*p) &&
(...skipping 1013 matching lines...) Expand 10 before | Expand all | Expand 10 after
2472 if (!old_generation_size_configured_ && tracer()->SurvivalEventsRecorded()) { 2497 if (!old_generation_size_configured_ && tracer()->SurvivalEventsRecorded()) {
2473 old_generation_allocation_limit_ = 2498 old_generation_allocation_limit_ =
2474 Max(kMinimumOldGenerationAllocationLimit, 2499 Max(kMinimumOldGenerationAllocationLimit,
2475 static_cast<intptr_t>( 2500 static_cast<intptr_t>(
2476 static_cast<double>(old_generation_allocation_limit_) * 2501 static_cast<double>(old_generation_allocation_limit_) *
2477 (tracer()->AverageSurvivalRatio() / 100))); 2502 (tracer()->AverageSurvivalRatio() / 100)));
2478 } 2503 }
2479 } 2504 }
2480 2505
2481 2506
2507 void Heap::ConfigureNewGenerationSize() {
2508 if (!new_space_high_promotion_mode_active_ &&
2509 new_space_.TotalCapacity() == new_space_.MaximumCapacity() &&
2510 IsStableOrIncreasingSurvivalTrend() && IsHighSurvivalRate()) {
2511 // Stable high survival rates even though young generation is at
2512 // maximum capacity indicates that most objects will be promoted.
2513 // To decrease scavenger pauses and final mark-sweep pauses, we
2514 // have to limit maximal capacity of the young generation.
2515 new_space_high_promotion_mode_active_ = true;
2516 if (FLAG_trace_gc) {
2517 PrintPID("Limited new space size due to high promotion rate: %d MB\n",
2518 new_space_.InitialTotalCapacity() / MB);
2519 }
2520 } else if (new_space_high_promotion_mode_active_ &&
2521 IsStableOrDecreasingSurvivalTrend() && IsLowSurvivalRate()) {
2522 // Decreasing low survival rates might indicate that the above high
2523 // promotion mode is over and we should allow the young generation
2524 // to grow again.
2525 new_space_high_promotion_mode_active_ = false;
2526 if (FLAG_trace_gc) {
2527 PrintPID("Unlimited new space size due to low promotion rate: %d MB\n",
2528 new_space_.MaximumCapacity() / MB);
2529 }
2530 }
2531
2532 if (new_space_high_promotion_mode_active_ &&
2533 new_space_.TotalCapacity() > new_space_.InitialTotalCapacity()) {
2534 new_space_.Shrink();
2535 }
2536 }
2537
2538
2482 AllocationResult Heap::AllocatePartialMap(InstanceType instance_type, 2539 AllocationResult Heap::AllocatePartialMap(InstanceType instance_type,
2483 int instance_size) { 2540 int instance_size) {
2484 Object* result = nullptr; 2541 Object* result = nullptr;
2485 AllocationResult allocation = AllocateRaw(Map::kSize, MAP_SPACE, MAP_SPACE); 2542 AllocationResult allocation = AllocateRaw(Map::kSize, MAP_SPACE, MAP_SPACE);
2486 if (!allocation.To(&result)) return allocation; 2543 if (!allocation.To(&result)) return allocation;
2487 2544
2488 // Map::cast cannot be used due to uninitialized map field. 2545 // Map::cast cannot be used due to uninitialized map field.
2489 reinterpret_cast<Map*>(result)->set_map(raw_unchecked_meta_map()); 2546 reinterpret_cast<Map*>(result)->set_map(raw_unchecked_meta_map());
2490 reinterpret_cast<Map*>(result)->set_instance_type(instance_type); 2547 reinterpret_cast<Map*>(result)->set_instance_type(instance_type);
2491 reinterpret_cast<Map*>(result)->set_instance_size(instance_size); 2548 reinterpret_cast<Map*>(result)->set_instance_size(instance_size);
(...skipping 4061 matching lines...) Expand 10 before | Expand all | Expand 10 after
6553 *object_type = "CODE_TYPE"; \ 6610 *object_type = "CODE_TYPE"; \
6554 *object_sub_type = "CODE_AGE/" #name; \ 6611 *object_sub_type = "CODE_AGE/" #name; \
6555 return true; 6612 return true;
6556 CODE_AGE_LIST_COMPLETE(COMPARE_AND_RETURN_NAME) 6613 CODE_AGE_LIST_COMPLETE(COMPARE_AND_RETURN_NAME)
6557 #undef COMPARE_AND_RETURN_NAME 6614 #undef COMPARE_AND_RETURN_NAME
6558 } 6615 }
6559 return false; 6616 return false;
6560 } 6617 }
6561 } // namespace internal 6618 } // namespace internal
6562 } // namespace v8 6619 } // namespace v8
OLDNEW
« no previous file with comments | « src/heap/heap.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698