OLD | NEW |
---|---|
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/pages.h" | 5 #include "vm/pages.h" |
6 | 6 |
7 #include "platform/assert.h" | 7 #include "platform/assert.h" |
8 #include "vm/compiler_stats.h" | 8 #include "vm/compiler_stats.h" |
9 #include "vm/gc_marker.h" | 9 #include "vm/gc_marker.h" |
10 #include "vm/gc_sweeper.h" | 10 #include "vm/gc_sweeper.h" |
(...skipping 1139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1150 grow_heap_); | 1150 grow_heap_); |
1151 } | 1151 } |
1152 return needs_gc; | 1152 return needs_gc; |
1153 } | 1153 } |
1154 | 1154 |
1155 | 1155 |
1156 void PageSpaceController::EvaluateGarbageCollection( | 1156 void PageSpaceController::EvaluateGarbageCollection( |
1157 SpaceUsage before, SpaceUsage after, int64_t start, int64_t end) { | 1157 SpaceUsage before, SpaceUsage after, int64_t start, int64_t end) { |
1158 ASSERT(end >= start); | 1158 ASSERT(end >= start); |
1159 history_.AddGarbageCollectionTime(start, end); | 1159 history_.AddGarbageCollectionTime(start, end); |
1160 int gc_time_fraction = history_.GarbageCollectionTimeFraction(); | 1160 const int gc_time_fraction = history_.GarbageCollectionTimeFraction(); |
1161 heap_->RecordData(PageSpace::kGCTimeFraction, gc_time_fraction); | 1161 heap_->RecordData(PageSpace::kGCTimeFraction, gc_time_fraction); |
1162 | 1162 |
1163 // Assume garbage increases linearly with allocation: | 1163 // Assume garbage increases linearly with allocation: |
1164 // G = kA, and estimate k from the previous cycle. | 1164 // G = kA, and estimate k from the previous cycle. |
1165 intptr_t allocated_since_previous_gc = | 1165 const intptr_t allocated_since_previous_gc = |
1166 before.used_in_words - last_usage_.used_in_words; | 1166 before.used_in_words - last_usage_.used_in_words; |
1167 intptr_t garbage = before.used_in_words - after.used_in_words; | 1167 ASSERT(allocated_since_previous_gc > 0); |
1168 double k = garbage / static_cast<double>(allocated_since_previous_gc); | 1168 const intptr_t garbage = before.used_in_words - after.used_in_words; |
1169 heap_->RecordData(PageSpace::kGarbageRatio, static_cast<int>(k * 100)); | 1169 ASSERT(garbage >= 0); |
1170 const double k = garbage / static_cast<double>(allocated_since_previous_gc); | |
1171 const int garbage_ratio = static_cast<int>(k * 100); | |
1172 heap_->RecordData(PageSpace::kGarbageRatio, garbage_ratio); | |
1170 | 1173 |
1171 // Define GC to be 'worthwhile' iff at least fraction t of heap is garbage. | 1174 // Define GC to be 'worthwhile' iff at least fraction t of heap is garbage. |
1172 double t = 1.0 - desired_utilization_; | 1175 double t = 1.0 - desired_utilization_; |
1173 // If we spend too much time in GC, strive for even more free space. | 1176 // If we spend too much time in GC, strive for even more free space. |
1174 if (gc_time_fraction > garbage_collection_time_ratio_) { | 1177 if (gc_time_fraction > garbage_collection_time_ratio_) { |
1175 t += (gc_time_fraction - garbage_collection_time_ratio_) / 100.0; | 1178 t += (gc_time_fraction - garbage_collection_time_ratio_) / 100.0; |
1176 } | 1179 } |
1177 | 1180 |
1178 // Find minimum 'grow_heap_' such that after increasing capacity by | 1181 if (garbage_ratio == 0) { |
zra
2016/08/11 18:29:15
Why 0? Why not e.g. <= 5? Maybe add TODO to invest
siva
2016/08/11 23:05:52
I did not want to change the growth pattern when g
| |
1179 // 'grow_heap_' pages and filling them, we expect a GC to be worthwhile. | 1182 // No garbage in the previous cycle so it would be hard to compute a |
1180 for (grow_heap_ = 0; grow_heap_ < heap_growth_max_; ++grow_heap_) { | 1183 // grow_heap_ size based on estimated garbage so we use growth ratio |
1181 intptr_t limit = | 1184 // instead. |
1182 after.capacity_in_words + (grow_heap_ * PageSpace::kPageSizeInWords); | 1185 const intptr_t grow_ratio = ( |
1183 intptr_t allocated_before_next_gc = limit - after.used_in_words; | 1186 static_cast<intptr_t>(after.capacity_in_words / desired_utilization_) - |
1184 double estimated_garbage = k * allocated_before_next_gc; | 1187 - after.capacity_in_words) / PageSpace::kPageSizeInWords; |
zra
2016/08/11 18:29:16
There are two '-'. One at the end of the previous
siva
2016/08/11 23:05:51
Good catch.
| |
1185 if (t <= estimated_garbage / limit) { | 1188 grow_heap_ = Utils::Maximum(static_cast<intptr_t>(heap_growth_max_), |
1186 break; | 1189 grow_ratio); |
1190 } else { | |
1191 // Find minimum 'grow_heap_' such that after increasing capacity by | |
1192 // 'grow_heap_' pages and filling them, we expect a GC to be worthwhile. | |
1193 intptr_t max = heap_growth_max_; | |
1194 intptr_t min = 0; | |
1195 intptr_t adjustment = 0; | |
1196 grow_heap_ = 0; | |
zra
2016/08/11 18:29:15
Maybe use a local, and then write the field at the
siva
2016/08/11 23:05:51
Done.
| |
1197 while (min < max) { | |
1198 grow_heap_ = (max + min) / 2; | |
1199 const intptr_t limit = | |
1200 after.capacity_in_words + (grow_heap_ * PageSpace::kPageSizeInWords); | |
1201 const intptr_t allocated_before_next_gc = limit - after.used_in_words; | |
1202 const double estimated_garbage = k * allocated_before_next_gc; | |
1203 if (t <= estimated_garbage / limit) { | |
1204 max = grow_heap_ - 1; | |
1205 adjustment = -1; | |
1206 } else { | |
1207 min = grow_heap_ + 1; | |
1208 adjustment = 1; | |
1209 } | |
1187 } | 1210 } |
1211 grow_heap_ += adjustment; | |
zra
2016/08/11 18:29:16
Why is this adjustment needed? If the search resul
siva
2016/08/11 23:05:52
I added the adjustment to keep it in sync with the
| |
1188 } | 1212 } |
1189 heap_->RecordData(PageSpace::kPageGrowth, grow_heap_); | 1213 heap_->RecordData(PageSpace::kPageGrowth, grow_heap_); |
1214 if (garbage_ratio == 0) { | |
1215 OS::PrintErr("grow_heap_ = %" Pd "\n", grow_heap_); | |
zra
2016/08/11 18:29:16
Leftover debug print?
siva
2016/08/11 23:05:52
Removed.
| |
1216 } | |
1190 | 1217 |
1191 // Limit shrinkage: allow growth by at least half the pages freed by GC. | 1218 // Limit shrinkage: allow growth by at least half the pages freed by GC. |
1192 intptr_t freed_pages = | 1219 const intptr_t freed_pages = |
1193 (before.capacity_in_words - after.capacity_in_words) / | 1220 (before.capacity_in_words - after.capacity_in_words) / |
1194 PageSpace::kPageSizeInWords; | 1221 PageSpace::kPageSizeInWords; |
1195 grow_heap_ = Utils::Maximum(grow_heap_, freed_pages / 2); | 1222 grow_heap_ = Utils::Maximum(grow_heap_, freed_pages / 2); |
1196 heap_->RecordData(PageSpace::kAllowedGrowth, grow_heap_); | 1223 heap_->RecordData(PageSpace::kAllowedGrowth, grow_heap_); |
1197 last_usage_ = after; | 1224 last_usage_ = after; |
1198 } | 1225 } |
1199 | 1226 |
1200 | 1227 |
1201 void PageSpaceGarbageCollectionHistory:: | 1228 void PageSpaceGarbageCollectionHistory:: |
1202 AddGarbageCollectionTime(int64_t start, int64_t end) { | 1229 AddGarbageCollectionTime(int64_t start, int64_t end) { |
(...skipping 17 matching lines...) Expand all Loading... | |
1220 return 0; | 1247 return 0; |
1221 } else { | 1248 } else { |
1222 ASSERT(total_time >= gc_time); | 1249 ASSERT(total_time >= gc_time); |
1223 int result = static_cast<int>((static_cast<double>(gc_time) / | 1250 int result = static_cast<int>((static_cast<double>(gc_time) / |
1224 static_cast<double>(total_time)) * 100); | 1251 static_cast<double>(total_time)) * 100); |
1225 return result; | 1252 return result; |
1226 } | 1253 } |
1227 } | 1254 } |
1228 | 1255 |
1229 } // namespace dart | 1256 } // namespace dart |
OLD | NEW |