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

Side by Side Diff: runtime/vm/pages.cc

Issue 10442073: Implement growth policy for old space using time and space signals. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 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 | Annotate | Revision Log
« runtime/vm/pages.h ('K') | « runtime/vm/pages.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 (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/gc_marker.h" 8 #include "vm/gc_marker.h"
9 #include "vm/gc_sweeper.h" 9 #include "vm/gc_sweeper.h"
10 #include "vm/object.h" 10 #include "vm/object.h"
11 #include "vm/virtual_memory.h" 11 #include "vm/virtual_memory.h"
12 12
13 namespace dart { 13 namespace dart {
14 14
15 DEFINE_FLAG(int, heap_growth_space_ratio, 10,
16 "The desired maximum percentage of free space after GC");
17 DEFINE_FLAG(int, heap_growth_time_ratio, 3,
18 "The desired maximum percentage of time spent in GC");
19 DEFINE_FLAG(int, heap_growth_rate, 4,
20 "The size the heap is grown, in heap pages");
21
15 HeapPage* HeapPage::Initialize(VirtualMemory* memory, bool is_executable) { 22 HeapPage* HeapPage::Initialize(VirtualMemory* memory, bool is_executable) {
16 ASSERT(memory->size() > VirtualMemory::PageSize()); 23 ASSERT(memory->size() > VirtualMemory::PageSize());
17 memory->Commit(is_executable); 24 memory->Commit(is_executable);
18 25
19 HeapPage* result = reinterpret_cast<HeapPage*>(memory->address()); 26 HeapPage* result = reinterpret_cast<HeapPage*>(memory->address());
20 result->memory_ = memory; 27 result->memory_ = memory;
21 result->next_ = NULL; 28 result->next_ = NULL;
22 result->used_ = 0; 29 result->used_ = 0;
23 result->top_ = result->first_object_start(); 30 result->top_ = result->first_object_start();
24 return result; 31 return result;
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
57 if (raw_obj->FindObject(visitor)) { 64 if (raw_obj->FindObject(visitor)) {
58 return raw_obj; // Found object, return it. 65 return raw_obj; // Found object, return it.
59 } 66 }
60 obj_addr += raw_obj->Size(); 67 obj_addr += raw_obj->Size();
61 } 68 }
62 ASSERT(obj_addr == end_addr); 69 ASSERT(obj_addr == end_addr);
63 return Object::null(); 70 return Object::null();
64 } 71 }
65 72
66 73
67 PageSpace::PageSpace(Heap* heap, intptr_t max_capacity, bool is_executable) 74 PageSpace::PageSpace(Heap* heap,
75 intptr_t max_capacity,
76 bool is_executable)
Ivan Posva 2012/05/29 23:27:37 ?
cshapiro 2012/05/30 17:56:24 More noise. Done.
68 : freelist_(), 77 : freelist_(),
69 heap_(heap), 78 heap_(heap),
70 pages_(NULL), 79 pages_(NULL),
71 pages_tail_(NULL), 80 pages_tail_(NULL),
72 large_pages_(NULL), 81 large_pages_(NULL),
73 bump_page_(NULL), 82 bump_page_(NULL),
74 max_capacity_(max_capacity), 83 max_capacity_(max_capacity),
75 capacity_(0), 84 capacity_(0),
76 in_use_(0), 85 in_use_(0),
77 count_(0), 86 count_(0),
78 is_executable_(is_executable), 87 is_executable_(is_executable),
79 sweeping_(false) { } 88 sweeping_(false),
89 is_growth_controlled_(false),
90 page_space_controller_(FLAG_heap_growth_space_ratio,
91 FLAG_heap_growth_rate,
92 FLAG_heap_growth_time_ratio) {
93 }
80 94
81 95
82 PageSpace::~PageSpace() { 96 PageSpace::~PageSpace() {
83 FreePages(pages_); 97 FreePages(pages_);
84 FreePages(large_pages_); 98 FreePages(large_pages_);
85 } 99 }
86 100
87 101
88 intptr_t PageSpace::LargePageSizeFor(intptr_t size) { 102 intptr_t PageSpace::LargePageSizeFor(intptr_t size) {
89 intptr_t page_size = Utils::RoundUp(size + sizeof(HeapPage), 103 intptr_t page_size = Utils::RoundUp(size + sizeof(HeapPage),
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
180 194
181 195
182 uword PageSpace::TryAllocate(intptr_t size) { 196 uword PageSpace::TryAllocate(intptr_t size) {
183 ASSERT(size >= kObjectAlignment); 197 ASSERT(size >= kObjectAlignment);
184 ASSERT(Utils::IsAligned(size, kObjectAlignment)); 198 ASSERT(Utils::IsAligned(size, kObjectAlignment));
185 uword result = 0; 199 uword result = 0;
186 if (size < kAllocatablePageSize) { 200 if (size < kAllocatablePageSize) {
187 result = TryBumpAllocate(size); 201 result = TryBumpAllocate(size);
188 if (result == 0) { 202 if (result == 0) {
189 result = freelist_.TryAllocate(size); 203 result = freelist_.TryAllocate(size);
190 if ((result == 0) && CanIncreaseCapacity(kPageSize)) { 204 if ((result == 0) &&
205 (is_growth_controlled_ != true ||
206 page_space_controller_.CanGrowPageSpace()) &&
207 CanIncreaseCapacity(kPageSize)) {
191 AllocatePage(); 208 AllocatePage();
192 result = TryBumpAllocate(size); 209 result = TryBumpAllocate(size);
193 ASSERT(result != 0); 210 ASSERT(result != 0);
194 } 211 }
195 } 212 }
196 } else { 213 } else {
197 // Large page allocation. 214 // Large page allocation.
198 intptr_t page_size = LargePageSizeFor(size); 215 intptr_t page_size = LargePageSizeFor(size);
199 if (page_size < size) { 216 if (page_size < size) {
200 // On overflow we fail to allocate. 217 // On overflow we fail to allocate.
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
281 NoHandleScope no_handles(isolate); 298 NoHandleScope no_handles(isolate);
282 299
283 if (FLAG_verify_before_gc) { 300 if (FLAG_verify_before_gc) {
284 OS::PrintErr("Verifying before MarkSweep... "); 301 OS::PrintErr("Verifying before MarkSweep... ");
285 heap_->Verify(); 302 heap_->Verify();
286 OS::PrintErr(" done.\n"); 303 OS::PrintErr(" done.\n");
287 } 304 }
288 305
289 Timer timer(FLAG_verbose_gc, "MarkSweep"); 306 Timer timer(FLAG_verbose_gc, "MarkSweep");
290 timer.Start(); 307 timer.Start();
308 int64_t start = OS::GetCurrentTimeMillis();
291 309
292 // Mark all reachable old-gen objects. 310 // Mark all reachable old-gen objects.
293 GCMarker marker(heap_); 311 GCMarker marker(heap_);
294 marker.MarkObjects(isolate, this, invoke_api_callbacks); 312 marker.MarkObjects(isolate, this, invoke_api_callbacks);
295 313
296 // Reset the bump allocation page to unused. 314 // Reset the bump allocation page to unused.
297 bump_page_ = NULL; 315 bump_page_ = NULL;
298 // Reset the freelists and setup sweeping. 316 // Reset the freelists and setup sweeping.
299 freelist_.Reset(); 317 freelist_.Reset();
300 GCSweeper sweeper(heap_); 318 GCSweeper sweeper(heap_);
(...skipping 23 matching lines...) Expand all
324 FreeLargePage(page, prev_page); 342 FreeLargePage(page, prev_page);
325 } else { 343 } else {
326 in_use += page_in_use; 344 in_use += page_in_use;
327 prev_page = page; 345 prev_page = page;
328 } 346 }
329 // Advance to the next page. 347 // Advance to the next page.
330 page = next_page; 348 page = next_page;
331 } 349 }
332 350
333 // Record data and print if requested. 351 // Record data and print if requested.
352 int64_t end = OS::GetCurrentTimeMillis();
Ivan Posva 2012/05/29 23:27:37 Why not use the timer object?
cshapiro 2012/05/30 17:56:24 Okay. The timer does not directly provide this da
334 intptr_t in_use_before = in_use_; 353 intptr_t in_use_before = in_use_;
354 page_space_controller_.EvaluateGarbageCollection(in_use_before, in_use,
355 start, end);
335 in_use_ = in_use; 356 in_use_ = in_use;
336 357
337 timer.Stop(); 358 timer.Stop();
338 if (FLAG_verbose_gc) { 359 if (FLAG_verbose_gc) {
339 const intptr_t KB2 = KB / 2; 360 const intptr_t KB2 = KB / 2;
340 OS::PrintErr("Mark-Sweep[%d]: %lldus (%dK -> %dK, %dK)\n", 361 OS::PrintErr("Mark-Sweep[%d]: %lldus (%dK -> %dK, %dK)\n",
341 count_, 362 count_,
342 timer.TotalElapsedTime(), 363 timer.TotalElapsedTime(),
343 (in_use_before + (KB2)) / KB, 364 (in_use_before + (KB2)) / KB,
344 (in_use + (KB2)) / KB, 365 (in_use + (KB2)) / KB,
345 (capacity_ + KB2) / KB); 366 (capacity_ + KB2) / KB);
346 } 367 }
347 368
348 if (FLAG_verify_after_gc) { 369 if (FLAG_verify_after_gc) {
349 OS::PrintErr("Verifying after MarkSweep... "); 370 OS::PrintErr("Verifying after MarkSweep... ");
350 heap_->Verify(); 371 heap_->Verify();
351 OS::PrintErr(" done.\n"); 372 OS::PrintErr(" done.\n");
352 } 373 }
353 374
354 count_++; 375 count_++;
355 // Done, reset the marker. 376 // Done, reset the marker.
356 ASSERT(sweeping_); 377 ASSERT(sweeping_);
357 sweeping_ = false; 378 sweeping_ = false;
358 } 379 }
359 380
381
382 PageSpaceController::PageSpaceController(int heap_growth_ratio,
383 int heap_growth_rate,
384 int garbage_collection_time_ratio)
385 : grow_heap_(heap_growth_rate),
386 heap_growth_ratio_(heap_growth_ratio),
387 heap_growth_rate_(heap_growth_rate),
388 garbage_collection_time_ratio_(garbage_collection_time_ratio) {
389 }
390
391
392 PageSpaceController::~PageSpaceController() {}
393
394
395 bool PageSpaceController::CanGrowPageSpace() {
396 if (heap_growth_ratio_ == 100) {
Ivan Posva 2012/05/29 23:27:37 For debugging we might want to add a always_grow_t
cshapiro 2012/05/30 17:56:24 Or, I could suppress the enabling of the controlle
397 return true;
398 }
399 if (grow_heap_ == 0) {
Ivan Posva 2012/05/29 23:27:37 <= 0
cshapiro 2012/05/30 17:56:24 Done.
400 return false;
401 }
402 grow_heap_ -= 1;
403 return true;
404 }
405
406
407 void PageSpaceController::EvaluateGarbageCollection(
408 size_t in_use_before, size_t in_use_after, int64_t start, int64_t end) {
409 ASSERT(in_use_before >= in_use_after);
410 ASSERT(end >= start);
411 history_.AddGarbageCollectionTime(start, end);
412 int collected_garbage_ratio =
413 static_cast<int>((static_cast<double>(in_use_before - in_use_after) /
414 static_cast<double>(in_use_before)) * 100);
415 if ((collected_garbage_ratio > heap_growth_ratio_) &&
416 (history_.GarbageCollectionTimeFraction() <
417 garbage_collection_time_ratio_)) {
418 grow_heap_ = 0;
419 } else {
420 grow_heap_ = heap_growth_rate_;
421 }
422 }
423
424
425 PageSpaceGarbageCollectionHistory::PageSpaceGarbageCollectionHistory()
426 : index_(0) {
427 for (uint32_t i = 0; i < kHistoryLength; i++) {
428 start_[i] = 0;
429 end_[i] = 0;
430 }
431 }
432
433
434 void PageSpaceGarbageCollectionHistory::
435 AddGarbageCollectionTime(uint64_t start, uint64_t end) {
436 int index = index_ % kHistoryLength;
437 start_[index] = start;
438 end_[index] = end;
439 index_++;
440 }
441
442
443 int PageSpaceGarbageCollectionHistory::GarbageCollectionTimeFraction() {
444 int current;
445 int previous;
446 uint64_t gc_time = 0;
447 uint64_t total_time = 0;
448 for (uint32_t i = 1; i < kHistoryLength; i++) {
449 current = (index_ - i) % kHistoryLength;
450 previous = (index_ - 1 - i) % kHistoryLength;
451 if (end_[previous] == 0) {
452 break;
453 }
454 // iterate over the circular buffer in reverse order
455 gc_time += end_[current] - start_[current];
456 total_time += end_[current] - end_[previous];
457 }
458 if (total_time == 0) {
459 return 0;
460 } else {
461 return static_cast<int>((static_cast<double>(gc_time) /
462 static_cast<double>(total_time))*100);
463 }
464 }
465
360 } // namespace dart 466 } // namespace dart
OLDNEW
« runtime/vm/pages.h ('K') | « runtime/vm/pages.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698