Skip to content

Commit

Permalink
Removed young generation auto-tuning.
Browse files Browse the repository at this point in the history
  • Loading branch information
brixen committed Jun 25, 2015
1 parent d63ccf5 commit a8dcb34
Show file tree
Hide file tree
Showing 15 changed files with 72 additions and 475 deletions.
28 changes: 5 additions & 23 deletions library/rubinius/configuration.rb
Expand Up @@ -4,33 +4,15 @@
Rubinius::ConfigurationVariables.define do |c|

c.section "gc" do |s|
s.vm_variable "young_initial_bytes", 3145728,
"The initial number of bytes the young generation of the GC should use"

s.vm_variable "young_max_bytes", 5 * 3145728,
"The maximum number of bytes the young generation of the GC should use"

s.vm_variable "young_autotune_size", true,
"Set whether or not the young GC should autotune the size"

s.vm_variable "young_autotune_factor", 8,
"Set the young GC size autotune factor. This is the denominator of the fraction of total memory used for young GC"
s.vm_variable "young_bytes", (40 * 1024 * 1024),
"The number of bytes the young generation of the GC should use"

s.vm_variable "young_lifetime", 2,
"How many young GC cycles an object lives before promotion"

s.vm_variable "young_autotune_lifetime", true,
"Set whether or not the young GC should adjust promotion age for performance"

s.vm_variable "large_object", (50 * 1024),
s.vm_variable "large_object", (1024 * 1024),
"The size (in bytes) of the large object threshold"

s.vm_variable "show", :bool,
"Display information whenever the GC runs"

s.vm_variable "noisy", :bool,
"Beep whenever the GC runs (once for young, twice for mature). Requires gc.show"

s.vm_variable "immix.concurrent", true,
"Set whether we want the Immix mark phase to run concurrently"

Expand All @@ -43,10 +25,10 @@
s.vm_variable "autopack", true,
"Set whether or not objects should be packed tightly in memory"

s.vm_variable "marksweep_threshold", (10 * 1024 * 1024),
s.vm_variable "marksweep_threshold", (25 * 1024 * 1024),
"The number of bytes allocated before the marksweep GC region is collected"

s.vm_variable "malloc_threshold", 104857600,
s.vm_variable "malloc_threshold", (25 * 1024 * 1024),
"How many bytes allocated by C extensions til the GC is run"
end

Expand Down
123 changes: 13 additions & 110 deletions vm/gc/baker.cpp
Expand Up @@ -10,6 +10,7 @@
#include "builtin/io.hpp"

#include "call_frame.hpp"
#include "configuration.hpp"

#include "gc/gc.hpp"

Expand All @@ -31,27 +32,16 @@ namespace rubinius {
* - Heap A and Heap B, which get one quarter of the heap each. Heaps A and B
* alternate between being the Current and Next space on each collection.
*/
BakerGC::BakerGC(ObjectMemory *om, size_t bytes)
BakerGC::BakerGC(ObjectMemory *om, Configuration& config)
: GarbageCollector(om)
, full(new Heap(bytes))
, eden(new Heap(full->allocate(bytes / 2), bytes / 2))
, heap_a(new Heap(full->allocate(bytes / 4), bytes / 4))
, heap_b(new Heap(full->allocate(bytes / 4), bytes / 4))
, full_new(NULL)
, eden_new(NULL)
, heap_a_new(NULL)
, heap_b_new(NULL)
, bytes_(config.gc_young_bytes * 2)
, full(new Heap(bytes_))
, eden(new Heap(full->allocate(bytes_ / 2), bytes_ / 2))
, heap_a(new Heap(full->allocate(bytes_ / 4), bytes_ / 4))
, heap_b(new Heap(full->allocate(bytes_ / 4), bytes_ / 4))
, current(heap_a)
, next(heap_b)
, total_objects(0)
, current_byte_size_(bytes)
, requested_byte_size_(bytes)
, original_lifetime_(1)
, lifetime_(1)
, copy_spills_(0)
, promoted_objects_(0)
, tune_threshold_(0)
, autotune_lifetime_(false)
, lifetime_(config.gc_young_lifetime)
{
reset();
}
Expand Down Expand Up @@ -98,9 +88,7 @@ namespace rubinius {
} else if(likely(next->enough_space_p(
obj->size_in_bytes(object_memory_->state())))) {
copy = next->move_object(object_memory_->state(), obj);
total_objects++;
} else {
copy_spills_++;
copy = object_memory_->promote_object(obj);
promoted_push(copy);
}
Expand Down Expand Up @@ -137,18 +125,10 @@ namespace rubinius {
return next->fully_scanned_p();
}

const static double cOverFullThreshold = 95.0;
const static int cOverFullTimes = 3;
const static size_t cMinimumLifetime = 1;

const static double cUnderFullThreshold = 20.0;
const static int cUnderFullTimes = -3;
const static size_t cMaximumLifetime = 6;

/**
* Perform garbage collection on the young objects.
*/
void BakerGC::collect(GCData* data, YoungCollectStats* stats) {
void BakerGC::collect(GCData* data) {

#ifdef HAVE_VALGRIND_H
(void)VALGRIND_MAKE_MEM_DEFINED(next->start().as_int(), next->size());
Expand All @@ -157,15 +137,8 @@ namespace rubinius {
mprotect(next->start(), next->size(), PROT_READ | PROT_WRITE);
mprotect(current->start(), current->size(), PROT_READ | PROT_WRITE);

check_growth_start();

ObjectArray *current_rs = object_memory_->swap_remember_set();

total_objects = 0;

copy_spills_ = 0;
reset_promoted();

// Start by copying objects in the remember set
for(ObjectArray::iterator oi = current_rs->begin();
oi != current_rs->end();
Expand Down Expand Up @@ -199,7 +172,10 @@ namespace rubinius {
}
}

for(Allocator<capi::Handle>::Iterator i(data->handles()->allocator()); i.more(); i.advance()) {
for(Allocator<capi::Handle>::Iterator i(data->handles()->allocator());
i.more();
i.advance())
{
if(!i->in_use_p()) continue;

if(!i->weak_p() && i->object()->young_object_p()) {
Expand Down Expand Up @@ -293,47 +269,9 @@ namespace rubinius {
Heap* x = next;
next = current;
current = x;

if(stats) {
stats->lifetime = lifetime_;
stats->percentage_used = current->percentage_used();
stats->promoted_objects = promoted_objects_;
stats->excess_objects = copy_spills_;
}

// Tune the age at which promotion occurs
if(autotune_lifetime_) {
double used = current->percentage_used();
if(used > cOverFullThreshold) {
if(tune_threshold_ >= cOverFullTimes) {
if(lifetime_ > cMinimumLifetime) lifetime_--;
} else {
tune_threshold_++;
}
} else if(used < cUnderFullThreshold) {
if(tune_threshold_ <= cUnderFullTimes) {
if(lifetime_ < cMaximumLifetime) lifetime_++;
} else {
tune_threshold_--;
}
} else if(tune_threshold_ > 0) {
tune_threshold_--;
} else if(tune_threshold_ < 0) {
tune_threshold_++;
} else if(tune_threshold_ == 0) {
if(lifetime_ < original_lifetime_) {
lifetime_++;
} else if(lifetime_ > original_lifetime_) {
lifetime_--;
}
}
}

}

void BakerGC::reset() {
check_growth_finish();

next->reset();
eden->reset();

Expand Down Expand Up @@ -362,41 +300,6 @@ namespace rubinius {
return true;
}

void BakerGC::check_growth_start() {
if(unlikely(current_byte_size_ != requested_byte_size_)) {

full_new = new Heap(requested_byte_size_);
eden_new = new Heap(full_new->allocate(requested_byte_size_ / 2), requested_byte_size_ / 2);
heap_a_new = new Heap(full_new->allocate(requested_byte_size_ / 4), requested_byte_size_ / 4);
heap_b_new = new Heap(full_new->allocate(requested_byte_size_ / 4), requested_byte_size_ / 4);

// Install the next pointer so we move objects to the new memory space.
next = heap_a_new;
}
}

void BakerGC::check_growth_finish() {
if(unlikely(full_new)) {
delete heap_a;
delete heap_b;
delete eden;
delete full;
heap_a = heap_a_new;
heap_b = heap_b_new;
eden = eden_new;
full = full_new;
current = heap_a_new;
next = heap_b_new;

heap_a_new = NULL;
heap_b_new = NULL;
eden_new = NULL;
full_new = NULL;

current_byte_size_ = requested_byte_size_;
}
}

void BakerGC::scan_mark_set() {
// Scan any mature objects in the mark set
// since they might refer to young objects.
Expand Down

0 comments on commit a8dcb34

Please sign in to comment.