Skip to content

Commit

Permalink
Added simple, per-thread, random interval sampling.
Browse files Browse the repository at this point in the history
This is mostly a temporary experiment that will likely be replaced with a
calling-context tree or similar structure and a separate profiler thread.
brixen committed May 11, 2016
1 parent a81c173 commit 0c3b9a4
Showing 7 changed files with 73 additions and 1 deletion.
7 changes: 6 additions & 1 deletion core/compiled_code.rb
Original file line number Diff line number Diff line change
@@ -44,7 +44,12 @@ def self.of_sender

def jitted?
Rubinius.primitive :compiledcode_jitted_p
raise PrimitiveFailure, "CompiledCode.jitted? primitive failed"
raise PrimitiveFailure, "CompiledCode#jitted? primitive failed"
end

def sample_count
Rubinius.primitive :compiledcode_sample_count
raise PrimitiveFailure, "CompiledCode#sample_count primitive failed"
end

# Returns the CompiledCode object for the currently executing Ruby
4 changes: 4 additions & 0 deletions machine/builtin/compiled_code.cpp
Original file line number Diff line number Diff line change
@@ -370,6 +370,10 @@ namespace rubinius {
return RBOOL(machine_code() && machine_code()->jitted_p());
}

Fixnum* CompiledCode::sample_count(STATE) {
return Fixnum::from(machine_code()->sample_count);
}

Object* CompiledCode::execute_script(STATE) {
state->thread_state()->clear();

3 changes: 3 additions & 0 deletions machine/builtin/compiled_code.hpp
Original file line number Diff line number Diff line change
@@ -127,6 +127,9 @@ namespace rubinius {
// Rubinius.primitive :compiledcode_jitted_p
Object* jitted_p(STATE);

// Rubinius.primitive :compiledcode_sample_count
Fixnum* sample_count(STATE);

String* full_name(STATE);

bool core_method(STATE);
1 change: 1 addition & 0 deletions machine/machine_code.cpp
Original file line number Diff line number Diff line change
@@ -58,6 +58,7 @@ namespace rubinius {
, splat_position(-1)
, stack_size(code->stack_size()->to_native())
, number_of_locals(code->number_of_locals())
, sample_count(0)
, call_count(0)
, uncommon_count(0)
, _call_site_count_(0)
1 change: 1 addition & 0 deletions machine/machine_code.hpp
Original file line number Diff line number Diff line change
@@ -69,6 +69,7 @@ namespace rubinius {
native_int stack_size;
native_int number_of_locals;

native_int sample_count;
native_int call_count;
native_int uncommon_count;

48 changes: 48 additions & 0 deletions machine/vm.cpp
Original file line number Diff line number Diff line change
@@ -87,6 +87,10 @@ namespace rubinius {
, current_fiber(this, nil<Fiber>())
, root_fiber(this, nil<Fiber>())
, waiting_object_(this, cNil)
, profile_(this, nil<Tuple>())
, profile_sample_count_(0)
, max_profile_entries_(15)
, min_profile_call_count_(0)
, native_method_environment(NULL)
, custom_wakeup_(NULL)
, custom_wakeup_data_(NULL)
@@ -252,6 +256,50 @@ namespace rubinius {
memory()->collect_maybe(state);
}

static int profile_compare(const void* a, const void* b) {
const CompiledCode* c_a = try_as<CompiledCode>(*(const Object**)(a));
const CompiledCode* c_b = try_as<CompiledCode>(*(const Object**)(b));

if(c_a && c_b) {
return c_a->machine_code()->call_count - c_b->machine_code()->call_count;
} else if(c_a) {
return 1;
} else if(c_b) {
return -1;
} else {
return 0;
}
}

void VM::update_profile(STATE) {
profile_sample_count_++;

CompiledCode* code = state->vm()->call_frame()->compiled_code;
code->machine_code()->sample_count++;

Tuple* profile = profile_.get();

if(profile->nil_p()) {
profile = Tuple::create(state, max_profile_entries_);
profile_.set(profile);
}

::qsort(reinterpret_cast<void*>(profile->field), profile->num_fields(),
sizeof(intptr_t), profile_compare);

for(native_int i = 0; i < profile->num_fields(); i++) {
if(code == profile->at(i)) return;
}

CompiledCode* pcode = try_as<CompiledCode>(profile->at(0));
if(!pcode || (pcode &&
code->machine_code()->call_count > pcode->machine_code()->call_count))
{
profile->put(state, 0, code);
min_profile_call_count_ = code->machine_code()->call_count;
}
}

static void suspend_thread() {
static int i = 0;
static int delay[] = {
10 changes: 10 additions & 0 deletions machine/vm.hpp
Original file line number Diff line number Diff line change
@@ -58,6 +58,7 @@ namespace rubinius {
class Symbol;
class ConfigParser;
class TypeError;
class Tuple;
class Assertion;
struct CallFrame;
class CallSiteInformation;
@@ -143,6 +144,11 @@ namespace rubinius {
/// Object that waits for inflation
memory::TypedRoot<Object*> waiting_object_;

memory::TypedRoot<Tuple*> profile_;
uint64_t profile_sample_count_;
native_int max_profile_entries_;
native_int min_profile_call_count_;

NativeMethodEnvironment* native_method_environment;

void (*custom_wakeup_)(void*);
@@ -407,6 +413,8 @@ namespace rubinius {

void collect_maybe(STATE);

void update_profile(STATE);

#define RBX_PROFILE_MAX_SHIFT 0xf
#define RBX_PROFILE_MAX_INTERVAL 0x1fff

@@ -429,6 +437,8 @@ namespace rubinius {
thread_nexus_->unlock();
}

update_profile(state);

set_profile_interval();
}
}

0 comments on commit 0c3b9a4

Please sign in to comment.