Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: rubinius/rubinius
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: d5251858f88c
Choose a base ref
...
head repository: rubinius/rubinius
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 533fbe0a9f19
Choose a head ref
  • 2 commits
  • 7 files changed
  • 1 contributor

Commits on May 16, 2016

  1. Shuffled Profiler code.

    brixen committed May 16, 2016
    Copy the full SHA
    a21b280 View commit details
  2. Copy the full SHA
    533fbe0 View commit details
Showing with 301 additions and 153 deletions.
  1. +1 −1 machine/builtin/thread.cpp
  2. +158 −0 machine/profiler.cpp
  3. +52 −0 machine/profiler.hpp
  4. +17 −26 machine/shared_state.cpp
  5. +7 −20 machine/shared_state.hpp
  6. +31 −81 machine/vm.cpp
  7. +35 −25 machine/vm.hpp
2 changes: 1 addition & 1 deletion machine/builtin/thread.cpp
Original file line number Diff line number Diff line change
@@ -382,7 +382,7 @@ namespace rubinius {
vm->thread->join_lock_.lock();
vm->thread->stopped();

vm->report_profile(state);
state->shared().report_profile(state);

memory::LockedObjects& locked_objects = state->vm()->locked_objects();
for(memory::LockedObjects::iterator i = locked_objects.begin();
158 changes: 158 additions & 0 deletions machine/profiler.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
#include "environment.hpp"
#include "machine_code.hpp"
#include "profiler.hpp"

#include "builtin/compiled_code.hpp"

#include <iostream>
#include <iomanip>
#include <fstream>

namespace rubinius {
namespace profiler {
ProfilerDiagnostics::ProfilerDiagnostics()
: diagnostics::DiagnosticsData()
{
set_type("Profiler");

document.AddMember("thread", 0, document.GetAllocator());
document.AddMember("samples", 0, document.GetAllocator());
document.AddMember("sample_average_time", 0.0, document.GetAllocator());
document.AddMember("total_time", 0.0, document.GetAllocator());
document.AddMember("entries", 0, document.GetAllocator());
}

Profiler::Profiler(STATE)
: path_()
, target_(eNone)
, diagnostics_data_(NULL)
{
std::string& target = state->shared().config.system_profiler_target.value;

if(!target.compare("none")) {
// target_(eNone)
} else if(!target.compare("diagnostics")) {
target_ = eDiagnostics;
} else {
target_ = ePath;
set_profiler_path(state);
}
}

void Profiler::set_profiler_path(STATE) {
path_ = state->shared().config.system_profiler_target.value;
state->shared().env()->expand_config_value(
path_, "$PID", state->shared().pid.c_str());
}

void Profiler::after_fork_child(STATE) {
if(target_ != eNone) {
if(state->shared().config.system_profiler_subprocess.value) {
set_profiler_path(state);
} else {
target_ = eNone;
}
}
}

void Profiler::report(STATE) {
switch(target_) {
case ePath:
report_to_file(state);
break;
case eDiagnostics:
report_to_diagnostics(state);
break;
default:
return;
}
}

void Profiler::report_to_file(STATE) {
state->vm()->sort_profile();
CompiledCode** profile = state->vm()->profile();

double total_time = state->vm()->run_time();

std::ofstream file;
file.open(path_, std::fstream::out | std::fstream::app);

file << "Profile: thread: " << state->vm()->thread_id()
<< ", samples: " << state->vm()->profile_sample_count()
<< ", sample avg time: " << (total_time / state->vm()->profile_sample_count()) << "s"
<< ", total time: " << total_time << "s" << std::endl;

state->vm()->sort_profile();

file << std::endl
<< std::setw(5) << "%"
<< std::setw(10) << "Samples"
<< " Method"
<< std::endl
<< "------------------------------------------------------------"
<< std::endl;

for(native_int i = 0; i < state->vm()->max_profile_entries(); i++) {
if(CompiledCode* code = try_as<CompiledCode>(profile[i])) {
double percentage = (double)code->machine_code()->sample_count
/ state->vm()->profile_sample_count() * 100;

file << std::setw(5) << std::setprecision(1) << std::fixed
<< percentage
<< std::setw(10)
<< code->machine_code()->sample_count
<< " "
<< *code->machine_code()->description()
<< std::endl;
}
}

file << std::endl;
file.close();
}

void Profiler::report_to_diagnostics(STATE) {
ProfilerDiagnostics* data = diagnostics_data();

state->vm()->sort_profile();
CompiledCode** profile = state->vm()->profile();

double total_time = state->vm()->run_time();
double sample_avg = total_time / state->vm()->profile_sample_count();

data->document["thread"] = state->vm()->thread_id();
data->document["samples"] = state->vm()->profile_sample_count();
data->document["sample_average_time"] = sample_avg;
data->document["total_time"] = total_time;

rapidjson::Value& entries = data->document["entries"];
entries.SetArray();

rapidjson::Document::AllocatorType& allocator = data->document.GetAllocator();

for(native_int i = 0; i < state->vm()->max_profile_entries(); i++) {
if(CompiledCode* code = try_as<CompiledCode>(profile[i])) {
rapidjson::Value percentage(
(double)code->machine_code()->sample_count
/ state->vm()->profile_sample_count() * 100);

rapidjson::Value samples((uint64_t)code->machine_code()->sample_count);

rapidjson::Value description;
description.SetString(code->machine_code()->description()->c_str(), allocator);

rapidjson::Value row = rapidjson::Value();
row.SetArray();

row.PushBack(percentage, allocator);
row.PushBack(samples, allocator);
row.PushBack(description, allocator);

data->document["entries"].PushBack(row, allocator);
}
}

state->shared().report_diagnostics(data);
}
}
}
52 changes: 52 additions & 0 deletions machine/profiler.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#ifndef RBX_PROFILER_H
#define RBX_PROFILER_H

#include "defines.hpp"
#include "diagnostics.hpp"

namespace rubinius {
namespace profiler {
class ProfilerDiagnostics : public diagnostics::DiagnosticsData {
public:
ProfilerDiagnostics();
virtual ~ProfilerDiagnostics() { }
};

enum ProfilerTarget {
eNone,
ePath,
eDiagnostics
};

class Profiler {
std::string path_;
ProfilerTarget target_;
ProfilerDiagnostics* diagnostics_data_;

public:
Profiler(STATE);

virtual ~Profiler() {
if(diagnostics_data_) delete diagnostics_data_;
}

ProfilerDiagnostics* diagnostics_data() {
if(!diagnostics_data_) {
diagnostics_data_ = new ProfilerDiagnostics();
}

return diagnostics_data_;
}

void set_profiler_path(STATE);

void report(STATE);
void report_to_file(STATE);
void report_to_diagnostics(STATE);

void after_fork_child(STATE);
};
}
}

#endif
43 changes: 17 additions & 26 deletions machine/shared_state.cpp
Original file line number Diff line number Diff line change
@@ -36,9 +36,7 @@ namespace rubinius {
, console_(NULL)
, metrics_(NULL)
, diagnostics_(NULL)
, profiler_path_()
, profiler_target_(eNone)
, profiler_enabled_(false)
, profiler_(NULL)
, start_time_(get_current_time())
, method_count_(1)
, class_count_(1)
@@ -94,6 +92,16 @@ namespace rubinius {
metrics_ = 0;
}

if(profiler_) {
delete profiler_;
profiler_ = 0;
}

if(diagnostics_) {
delete diagnostics_;
diagnostics_ = 0;
}

delete global_cache;
delete om;
delete internal_threads_;
@@ -166,22 +174,12 @@ namespace rubinius {
return diagnostics_;
}

void SharedState::set_profiler_path() {
profiler_path_ = config.system_profiler_target.value;
env()->expand_config_value(profiler_path_, "$PID", pid.c_str());
}

void SharedState::start_profiler(STATE) {
profiler_enabled_ = true;

if(!config.system_profiler_target.value.compare("none")) {
profiler_enabled_ = false;
} else if(!config.system_profiler_target.value.compare("diagnostics")) {
profiler_target_ = eDiagnostics;
} else {
profiler_target_ = ePath;
set_profiler_path();
profiler::Profiler* SharedState::start_profiler(STATE) {
if(!profiler_) {
profiler_ = new profiler::Profiler(state);
}

return profiler_;
}

void SharedState::after_fork_child(STATE) {
@@ -202,14 +200,7 @@ namespace rubinius {
om->after_fork_child(state);
signals_->after_fork_child(state);
console_->after_fork_child(state);

if(profiler_enabled_p()) {
if(config.system_profiler_subprocess.value) {
set_profiler_path();
} else {
profiler_enabled_ = false;
}
}
profiler_->after_fork_child(state);
}

const unsigned int* SharedState::object_memory_mark_address() const {
27 changes: 7 additions & 20 deletions machine/shared_state.hpp
Original file line number Diff line number Diff line change
@@ -9,6 +9,7 @@
#include "internal_threads.hpp"
#include "diagnostics.hpp"
#include "globals.hpp"
#include "profiler.hpp"
#include "symbol_table.hpp"
#include "thread_nexus.hpp"

@@ -80,13 +81,6 @@ namespace rubinius {
*/

class SharedState {
public:
enum ProfilerTarget {
eNone,
ePath,
eDiagnostics
};

private:
ThreadNexus* thread_nexus_;
InternalThreads* internal_threads_;
@@ -95,14 +89,11 @@ namespace rubinius {
console::Console* console_;
metrics::Metrics* metrics_;
diagnostics::Diagnostics* diagnostics_;
profiler::Profiler* profiler_;

CApiConstantNameMap capi_constant_name_map_;
CApiConstantHandleMap capi_constant_handle_map_;

std::string profiler_path_;
ProfilerTarget profiler_target_;
bool profiler_enabled_;

uint64_t start_time_;
uint64_t method_count_;
unsigned int class_count_;
@@ -241,18 +232,14 @@ namespace rubinius {
}
}

void start_profiler(STATE);
void set_profiler_path();
std::string& profiler_path() {
return profiler_path_;
}
profiler::Profiler* start_profiler(STATE);

bool profiler_enabled_p() {
return profiler_enabled_;
profiler::Profiler* profiler() const {
return profiler_;
}

ProfilerTarget profiler_target() {
return profiler_target_;
void report_profile(STATE) {
if(profiler_) profiler_->report(state);
}

Environment* env() const {
Loading