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

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: address review comments 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
« no previous file with comments | « runtime/vm/pages.h ('k') | runtime/vm/scavenger.h » ('j') | 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 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
69 heap_(heap), 76 heap_(heap),
70 pages_(NULL), 77 pages_(NULL),
71 pages_tail_(NULL), 78 pages_tail_(NULL),
72 large_pages_(NULL), 79 large_pages_(NULL),
73 bump_page_(NULL), 80 bump_page_(NULL),
74 max_capacity_(max_capacity), 81 max_capacity_(max_capacity),
75 capacity_(0), 82 capacity_(0),
76 in_use_(0), 83 in_use_(0),
77 count_(0), 84 count_(0),
78 is_executable_(is_executable), 85 is_executable_(is_executable),
79 sweeping_(false) { } 86 sweeping_(false),
87 page_space_controller_(FLAG_heap_growth_space_ratio,
88 FLAG_heap_growth_rate,
89 FLAG_heap_growth_time_ratio) {
90 }
80 91
81 92
82 PageSpace::~PageSpace() { 93 PageSpace::~PageSpace() {
83 FreePages(pages_); 94 FreePages(pages_);
84 FreePages(large_pages_); 95 FreePages(large_pages_);
85 } 96 }
86 97
87 98
88 intptr_t PageSpace::LargePageSizeFor(intptr_t size) { 99 intptr_t PageSpace::LargePageSizeFor(intptr_t size) {
89 intptr_t page_size = Utils::RoundUp(size + sizeof(HeapPage), 100 intptr_t page_size = Utils::RoundUp(size + sizeof(HeapPage),
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
180 191
181 192
182 uword PageSpace::TryAllocate(intptr_t size) { 193 uword PageSpace::TryAllocate(intptr_t size) {
183 ASSERT(size >= kObjectAlignment); 194 ASSERT(size >= kObjectAlignment);
184 ASSERT(Utils::IsAligned(size, kObjectAlignment)); 195 ASSERT(Utils::IsAligned(size, kObjectAlignment));
185 uword result = 0; 196 uword result = 0;
186 if (size < kAllocatablePageSize) { 197 if (size < kAllocatablePageSize) {
187 result = TryBumpAllocate(size); 198 result = TryBumpAllocate(size);
188 if (result == 0) { 199 if (result == 0) {
189 result = freelist_.TryAllocate(size); 200 result = freelist_.TryAllocate(size);
190 if ((result == 0) && CanIncreaseCapacity(kPageSize)) { 201 if ((result == 0) &&
202 page_space_controller_.CanGrowPageSpace(size) &&
203 CanIncreaseCapacity(kPageSize)) {
191 AllocatePage(); 204 AllocatePage();
192 result = TryBumpAllocate(size); 205 result = TryBumpAllocate(size);
193 ASSERT(result != 0); 206 ASSERT(result != 0);
194 } 207 }
195 } 208 }
196 } else { 209 } else {
197 // Large page allocation. 210 // Large page allocation.
198 intptr_t page_size = LargePageSizeFor(size); 211 intptr_t page_size = LargePageSizeFor(size);
199 if (page_size < size) { 212 if (page_size < size) {
200 // On overflow we fail to allocate. 213 // On overflow we fail to allocate.
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
279 sweeping_ = true; 292 sweeping_ = true;
280 Isolate* isolate = Isolate::Current(); 293 Isolate* isolate = Isolate::Current();
281 NoHandleScope no_handles(isolate); 294 NoHandleScope no_handles(isolate);
282 295
283 if (FLAG_verify_before_gc) { 296 if (FLAG_verify_before_gc) {
284 OS::PrintErr("Verifying before MarkSweep... "); 297 OS::PrintErr("Verifying before MarkSweep... ");
285 heap_->Verify(); 298 heap_->Verify();
286 OS::PrintErr(" done.\n"); 299 OS::PrintErr(" done.\n");
287 } 300 }
288 301
289 Timer timer(FLAG_verbose_gc, "MarkSweep"); 302 Timer timer(true, "MarkSweep");
290 timer.Start(); 303 timer.Start();
304 int64_t start = OS::GetCurrentTimeMillis();
291 305
292 // Mark all reachable old-gen objects. 306 // Mark all reachable old-gen objects.
293 GCMarker marker(heap_); 307 GCMarker marker(heap_);
294 marker.MarkObjects(isolate, this, invoke_api_callbacks); 308 marker.MarkObjects(isolate, this, invoke_api_callbacks);
295 309
296 // Reset the bump allocation page to unused. 310 // Reset the bump allocation page to unused.
297 bump_page_ = NULL; 311 bump_page_ = NULL;
298 // Reset the freelists and setup sweeping. 312 // Reset the freelists and setup sweeping.
299 freelist_.Reset(); 313 freelist_.Reset();
300 GCSweeper sweeper(heap_); 314 GCSweeper sweeper(heap_);
(...skipping 27 matching lines...) Expand all
328 } 342 }
329 // Advance to the next page. 343 // Advance to the next page.
330 page = next_page; 344 page = next_page;
331 } 345 }
332 346
333 // Record data and print if requested. 347 // Record data and print if requested.
334 intptr_t in_use_before = in_use_; 348 intptr_t in_use_before = in_use_;
335 in_use_ = in_use; 349 in_use_ = in_use;
336 350
337 timer.Stop(); 351 timer.Stop();
352
353 // Record signals for growth control.
354 int64_t elapsed = timer.TotalElapsedTime() * kMicrosecondsPerMillisecond;
355 page_space_controller_.EvaluateGarbageCollection(in_use_before, in_use,
356 start, start + elapsed);
357
338 if (FLAG_verbose_gc) { 358 if (FLAG_verbose_gc) {
339 const intptr_t KB2 = KB / 2; 359 const intptr_t KB2 = KB / 2;
340 OS::PrintErr("Mark-Sweep[%d]: %lldus (%dK -> %dK, %dK)\n", 360 OS::PrintErr("Mark-Sweep[%d]: %lldus (%dK -> %dK, %dK)\n",
341 count_, 361 count_,
342 timer.TotalElapsedTime(), 362 timer.TotalElapsedTime(),
343 (in_use_before + (KB2)) / KB, 363 (in_use_before + (KB2)) / KB,
344 (in_use + (KB2)) / KB, 364 (in_use + (KB2)) / KB,
345 (capacity_ + KB2) / KB); 365 (capacity_ + KB2) / KB);
346 } 366 }
347 367
348 if (FLAG_verify_after_gc) { 368 if (FLAG_verify_after_gc) {
349 OS::PrintErr("Verifying after MarkSweep... "); 369 OS::PrintErr("Verifying after MarkSweep... ");
350 heap_->Verify(); 370 heap_->Verify();
351 OS::PrintErr(" done.\n"); 371 OS::PrintErr(" done.\n");
352 } 372 }
353 373
354 count_++; 374 count_++;
355 // Done, reset the marker. 375 // Done, reset the marker.
356 ASSERT(sweeping_); 376 ASSERT(sweeping_);
357 sweeping_ = false; 377 sweeping_ = false;
358 } 378 }
359 379
380
381 PageSpaceController::PageSpaceController(int heap_growth_ratio,
382 int heap_growth_rate,
383 int garbage_collection_time_ratio)
384 : is_enabled_(false),
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(intptr_t size_in_bytes) {
396 size_in_bytes = Utils::RoundUp(size_in_bytes, PageSpace::kPageSize);
397 intptr_t size_in_pages = size_in_bytes / PageSpace::kPageSize;
398 if (!is_enabled_) {
399 return true;
400 }
401 if (heap_growth_ratio_ == 100) {
402 return true;
403 }
404 if (grow_heap_ <= 0) {
405 return false;
406 }
407 grow_heap_ -= size_in_pages;
408 return true;
409 }
410
411
412 void PageSpaceController::EvaluateGarbageCollection(
413 size_t in_use_before, size_t in_use_after, int64_t start, int64_t end) {
414 ASSERT(in_use_before >= in_use_after);
415 ASSERT(end >= start);
416 history_.AddGarbageCollectionTime(start, end);
417 int collected_garbage_ratio =
418 static_cast<int>((static_cast<double>(in_use_before - in_use_after) /
419 static_cast<double>(in_use_before)) * 100);
420 if ((collected_garbage_ratio > heap_growth_ratio_) &&
421 (history_.GarbageCollectionTimeFraction() <
422 garbage_collection_time_ratio_)) {
423 grow_heap_ = 0;
424 } else {
425 grow_heap_ = heap_growth_rate_;
426 }
427 }
428
429
430 PageSpaceGarbageCollectionHistory::PageSpaceGarbageCollectionHistory()
431 : index_(0) {
432 for (uint32_t i = 0; i < kHistoryLength; i++) {
433 start_[i] = 0;
434 end_[i] = 0;
435 }
436 }
437
438
439 void PageSpaceGarbageCollectionHistory::
440 AddGarbageCollectionTime(uint64_t start, uint64_t end) {
441 int index = index_ % kHistoryLength;
442 start_[index] = start;
443 end_[index] = end;
444 index_++;
445 }
446
447
448 int PageSpaceGarbageCollectionHistory::GarbageCollectionTimeFraction() {
449 int current;
450 int previous;
451 uint64_t gc_time = 0;
452 uint64_t total_time = 0;
453 for (uint32_t i = 1; i < kHistoryLength; i++) {
454 current = (index_ - i) % kHistoryLength;
455 previous = (index_ - 1 - i) % kHistoryLength;
456 if (end_[previous] == 0) {
457 break;
458 }
459 // iterate over the circular buffer in reverse order
460 gc_time += end_[current] - start_[current];
461 total_time += end_[current] - end_[previous];
462 }
463 if (total_time == 0) {
464 return 0;
465 } else {
466 return static_cast<int>((static_cast<double>(gc_time) /
467 static_cast<double>(total_time))*100);
468 }
469 }
470
360 } // namespace dart 471 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/pages.h ('k') | runtime/vm/scavenger.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698