Module: Rbkit
- Defined in:
- lib/rbkit.rb,
lib/rbkit/timer.rb,
lib/rbkit/version.rb,
lib/rbkit/rbkit_gc.rb,
ext/rbkit_tracer.c,
ext/rbkit_test_helper.c
Overview
Class implements user friendly interface in pure Ruby for profiler.
Defined Under Namespace
Classes: Profiler, RbkitGC, Timer
Constant Summary collapse
- DEFAULT_PUB_PORT =
5555
- DEFAULT_REQ_PORT =
5556
- VERSION =
"0.1.10"
- EVENT_TYPES =
rbkit_event_types_as_hash()
- MESSAGE_FIELDS =
()
Class Method Summary collapse
- .enable_test_mode ⇒ Object
- .get_queued_messages ⇒ Object
- .poll_for_request ⇒ Object
- .send_hash_as_event(*args) ⇒ Object
-
.send_messages ⇒ Object
Creates a msgpack array which contains all the messages packed after the last time send_messages() was called, and sends it over the PUB socket.
- .send_objectspace_dump ⇒ Object
-
.start_profiling(pub_port: DEFAULT_PUB_PORT, request_port: DEFAULT_REQ_PORT, enable_object_trace: true, enable_gc_stats: true) ⇒ Object
Starts the server with all tracepoints enabled by default.
-
.start_server(pub_port: DEFAULT_PUB_PORT, request_port: DEFAULT_REQ_PORT) ⇒ Object
Starts the Rbkit server and waits for a client to connect and issue commands to the request_port, until then there’s zero performance overhead.
- .start_stat_server(*args) ⇒ Object
- .start_stat_tracing ⇒ Object
- .status ⇒ Object
-
.stop_server ⇒ Object
Stops profiling and brings down the rbkit server if it’s running.
- .stop_stat_server ⇒ Object
- .stop_stat_tracing ⇒ Object
Class Method Details
.enable_test_mode ⇒ Object
347 348 349 350 |
# File 'ext/rbkit_tracer.c', line 347 static VALUE enable_test_mode() { Init_rbkit_test_helper(); return Qnil; } |
.get_queued_messages ⇒ Object
9 10 11 12 13 14 15 16 17 18 19 |
# File 'ext/rbkit_test_helper.c', line 9
static VALUE get_queued_messages() {
msgpack_sbuffer * sbuf = msgpack_sbuffer_new();
get_event_collection_message(sbuf);
if(sbuf && sbuf->size > 0) {
VALUE str = rb_str_new(sbuf->data, sbuf->size);
message_list_clear();
msgpack_sbuffer_destroy(sbuf);
return str;
}
return Qnil;
}
|
.poll_for_request ⇒ Object
213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 |
# File 'ext/rbkit_tracer.c', line 213
static VALUE poll_for_request() {
// Wait for 100 millisecond and check if there is a message
// we can't wait here indefenitely because ruby is not aware this is a
// blocking operation. Remember ruby releases GVL in a thread
// whenever it encounters a known blocking operation.
zmq_poll(items, 1, 100);
if (items[0].revents && ZMQ_POLLIN) {
char *message = tracer_string_recv(zmq_response_socket);
if(strcmp(message, "handshake") == 0) {
send_handshake_response();
} else {
tracer_string_send(zmq_response_socket, "ok");
}
VALUE command_ruby_string = rb_str_new_cstr(message);
free(message);
return command_ruby_string;
} else {
return Qnil;
}
}
|
.send_hash_as_event(*args) ⇒ Object
282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 |
# File 'ext/rbkit_tracer.c', line 282
static VALUE send_hash_as_event(int argc, VALUE *argv, VALUE self) {
VALUE hash_object;
VALUE event_type;
rb_scan_args(argc, argv, "20", &hash_object, &event_type);
msgpack_sbuffer *buffer = msgpack_sbuffer_new();
msgpack_packer *packer = msgpack_packer_new(buffer, msgpack_sbuffer_write);
rbkit_hash_event *event = new_rbkit_hash_event(FIX2INT(event_type), hash_object);
pack_event((rbkit_event_header *)event, packer);
free(event);
add_message(buffer);
msgpack_sbuffer_free(buffer);
msgpack_packer_free(packer);
return Qnil;
}
|
.send_messages ⇒ Object
Creates a msgpack array which contains all the messages packed after the last time send_messages() was called, and sends it over the PUB socket.
334 335 336 337 338 339 340 341 342 343 344 345 |
# File 'ext/rbkit_tracer.c', line 334
static VALUE send_messages() {
//Get all aggregated messages as payload of a single event.
msgpack_sbuffer * sbuf = msgpack_sbuffer_new();
get_event_collection_message(sbuf);
//Send the msgpack array over zmq PUB socket
if(sbuf && sbuf->size > 0)
zmq_send(zmq_publisher, sbuf->data, sbuf->size, 0);
// Clear the aggregated messages
message_list_clear();
msgpack_sbuffer_free(sbuf);
return Qnil;
}
|
.send_objectspace_dump ⇒ Object
314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 |
# File 'ext/rbkit_tracer.c', line 314
static VALUE send_objectspace_dump() {
msgpack_sbuffer* buffer = msgpack_sbuffer_new();
msgpack_packer* pk = msgpack_packer_new(buffer, msgpack_sbuffer_write);
rbkit_object_dump * dump = get_object_dump(logger->object_table);
rbkit_object_space_dump_event *event = new_rbkit_object_space_dump_event(dump);
pack_event((rbkit_event_header *)event, pk);
free(event);
add_message(buffer);
free(dump);
msgpack_sbuffer_free(buffer);
msgpack_packer_free(pk);
return Qnil;
}
|
.start_profiling(pub_port: DEFAULT_PUB_PORT, request_port: DEFAULT_REQ_PORT, enable_object_trace: true, enable_gc_stats: true) ⇒ Object
Starts the server with all tracepoints enabled by default. User can optionally disable tracepoints using the optional arguments. This method can be used to profile the startup process of a ruby application where sending commands from the client to enable profiling is not feasible.
106 107 108 109 110 111 |
# File 'lib/rbkit.rb', line 106 def self.start_profiling(pub_port: DEFAULT_PUB_PORT, request_port: DEFAULT_REQ_PORT, enable_object_trace: true, enable_gc_stats: true) @profiler ||= Rbkit::Profiler.new(pub_port, request_port) @profiler.start_server(enable_object_trace: enable_object_trace, enable_gc_stats: enable_gc_stats) end |
.start_server(pub_port: DEFAULT_PUB_PORT, request_port: DEFAULT_REQ_PORT) ⇒ Object
Starts the Rbkit server and waits for a client to connect and issue commands to the request_port, until then there’s zero performance overhead. Profiling data is sent asynchronously over pub_port. This method can be called early in a ruby application so that whenever profiling needs to be done, the client can attach itself to the inactive server, do the profiling and leave.
96 97 98 99 |
# File 'lib/rbkit.rb', line 96 def self.start_server(pub_port: DEFAULT_PUB_PORT, request_port: DEFAULT_REQ_PORT) @profiler ||= Rbkit::Profiler.new(pub_port, request_port) @profiler.start_server end |
.start_stat_server(*args) ⇒ Object
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
# File 'ext/rbkit_tracer.c', line 129
static VALUE start_stat_server(int argc, VALUE *argv, VALUE self) {
VALUE pub_port;
VALUE request_port;
int bind_result;
rb_scan_args(argc, argv, "02", &pub_port, &request_port);
char zmq_endpoint[14];
sprintf(zmq_endpoint, "tcp://*:%d", FIX2INT(pub_port));
zmq_context = zmq_ctx_new();
zmq_publisher = zmq_socket(zmq_context, ZMQ_PUB);
bind_result = zmq_bind(zmq_publisher, zmq_endpoint);
if(bind_result != 0)
return Qfalse;
char zmq_request_endpoint[14];
sprintf(zmq_request_endpoint, "tcp://*:%d", FIX2INT(request_port));
zmq_response_socket = zmq_socket(zmq_context, ZMQ_REP);
bind_result = zmq_bind(zmq_response_socket, zmq_request_endpoint);
if(bind_result != 0)
return Qfalse;
// Creates a list which aggregates messages
message_list_new();
logger = get_trace_logger();
logger->newobj_trace = rb_tracepoint_new(0, RUBY_INTERNAL_EVENT_NEWOBJ, newobj_i, logger);
logger->freeobj_trace = rb_tracepoint_new(0, RUBY_INTERNAL_EVENT_FREEOBJ, freeobj_i, logger);
rb_gc_register_mark_object(logger->newobj_trace);
rb_gc_register_mark_object(logger->freeobj_trace);
create_gc_hooks();
items[0].socket = zmq_response_socket;
items[0].events = ZMQ_POLLIN;
return Qtrue;
}
|
.start_stat_tracing ⇒ Object
301 302 303 304 305 306 307 308 309 310 311 312 |
# File 'ext/rbkit_tracer.c', line 301
static VALUE start_stat_tracing() {
if (logger->enabled == Qtrue)
return Qnil;
rb_tracepoint_enable(logger->newobj_trace);
rb_tracepoint_enable(logger->freeobj_trace);
int i = 0;
for (i=0; i<3; i++) {
rb_tracepoint_enable(logger->hooks[i]);
}
logger->enabled = Qtrue;
return Qnil;
}
|
.status ⇒ Object
186 187 188 189 190 191 192 193 194 195 196 |
# File 'ext/rbkit_tracer.c', line 186
static VALUE rbkit_status_as_hash() {
VALUE status = rb_hash_new();
VALUE pid = rb_funcall(rb_path2class("Process"), rb_intern("pid"), 0, 0);
VALUE processName = rb_funcall(rb_path2class("Process"), rb_intern("argv0"), 0, 0);
int object_trace_enabled = (logger && logger->enabled) ? 1 : 0;
rb_hash_aset(status, ID2SYM(rb_intern("process_name")), processName);
rb_hash_aset(status, ID2SYM(rb_intern("pwd")), rb_dir_getwd());
rb_hash_aset(status, ID2SYM(rb_intern("pid")), pid);
rb_hash_aset(status, ID2SYM(rb_intern("object_trace_enabled")), INT2FIX(object_trace_enabled));
return status;
}
|
.stop_server ⇒ Object
Stops profiling and brings down the rbkit server if it’s running
114 115 116 117 118 119 120 121 122 |
# File 'lib/rbkit.rb', line 114 def self.stop_server if !@profiler.nil? && @profiler.make_clean_exit @profiler = nil true else $stderr.puts "Cannot stop Rbkit server. Is it running?" false end end |
.stop_stat_server ⇒ Object
260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 |
# File 'ext/rbkit_tracer.c', line 260
static VALUE stop_stat_server() {
if (logger->enabled == Qtrue)
stop_stat_tracing();
// Destroy the list which aggregates messages
message_list_destroy();
// Clear object_table which holds object allocation info
st_foreach(logger->object_table, free_values_i, 0);
st_clear(logger->object_table);
st_foreach(logger->str_table, free_keys_i, 0);
st_clear(logger->str_table);
msgpack_sbuffer_free(logger->sbuf);
msgpack_packer_free(logger->msgpacker);
zmq_close(zmq_publisher);
zmq_close(zmq_response_socket);
zmq_ctx_destroy(zmq_context);
free(logger);
logger = 0;
return Qnil;
}
|
.stop_stat_tracing ⇒ Object
234 235 236 237 238 239 240 241 242 243 244 245 246 247 |
# File 'ext/rbkit_tracer.c', line 234
static VALUE stop_stat_tracing() {
if (logger->hooks[0] != 0) {
rb_tracepoint_disable(logger->hooks[0]);
rb_tracepoint_disable(logger->hooks[1]);
rb_tracepoint_disable(logger->hooks[2]);
}
if (logger->newobj_trace) {
rb_tracepoint_disable(logger->newobj_trace);
rb_tracepoint_disable(logger->freeobj_trace);
}
logger->enabled = Qfalse;
return Qnil;
}
|