Module: Rbkit
- Defined in:
- lib/rbkit.rb,
lib/rbkit/timer.rb,
lib/rbkit/version.rb,
ext/rbkit_tracer.c
Overview
Class implements user friendly interface in pure Ruby for profiler.
Defined Under Namespace
Constant Summary collapse
- VERSION =
"0.0.1"
Class Method Summary collapse
- .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 = nil, request_port = nil) ⇒ Object
Starts the server and enables memory profiling tracepoints.
-
.start_server(pub_port = nil, request_port = nil) ⇒ Object
Just starts the server and waits for instructions.
- .start_stat_server(*args) ⇒ Object
- .start_stat_tracing ⇒ 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
.poll_for_request ⇒ Object
307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 |
# File 'ext/rbkit_tracer.c', line 307 static VALUE poll_for_request() { // Wait for 100 millisecond and check if there is a // 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); 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
417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 |
# File 'ext/rbkit_tracer.c', line 417 static VALUE send_hash_as_event(int argc, VALUE *argv, VALUE self) { VALUE hash_object; VALUE event_name; rb_scan_args(argc, argv, "20", &hash_object, &event_name); int size = RHASH_SIZE(hash_object); msgpack_sbuffer *buffer = msgpack_sbuffer_new(); msgpack_packer *packer = msgpack_packer_new(buffer, msgpack_sbuffer_write); pack_event_header(packer, StringValueCStr(event_name), 3); pack_string(packer, "payload"); msgpack_pack_map(packer, size); rb_hash_foreach(hash_object, hash_iterator, (VALUE)packer); (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.
560 561 562 563 564 565 566 567 568 569 570 571 |
# File 'ext/rbkit_tracer.c', line 560 static VALUE () { //Get all aggregated as payload of a single event. msgpack_sbuffer * sbuf = msgpack_sbuffer_new(); (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 (); msgpack_sbuffer_free(sbuf); return Qnil; } |
.send_objectspace_dump ⇒ Object
451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 |
# File 'ext/rbkit_tracer.c', line 451 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); pack_event_header(pk, "object_space_dump", 3); pack_string(pk, "payload"); // Set size of array to hold all objects msgpack_pack_array(pk, dump->object_count); // Iterate through all object data rbkit_object_dump_page * page = dump->first ; while(page != NULL) { rbkit_object_data *data; size_t i = 0; for(;i < page->count; i++) { data = &(page->data[i]); /* Object dump is a map that looks like this : * { * object_id: <OBJECT_ID_IN_HEX>, * class: <CLASS_NAME>, * references: [<OBJECT_ID_IN_HEX>, <OBJECT_ID_IN_HEX>, ...], * file: <FILE_PATH>, * line: <LINE_NO>, * size: <SIZE> * } */ msgpack_pack_map(pk, 6); // Key1 : "object_id" pack_string(pk, "object_id"); // Value1 : pointer address of object char * object_id; asprintf(&object_id, "%p", data->object_id); pack_string(pk, object_id); free(object_id); // Key2 : "class_name" pack_string(pk, "class_name"); // Value2 : Class name of object if(data->class_name == NULL) { msgpack_pack_nil(pk); } else { pack_string(pk, data->class_name); } // Key3 : "references" pack_string(pk, "references"); // Value3 : References held by the object msgpack_pack_array(pk, data->reference_count); if(data->reference_count != 0) { size_t count = 0; for(; count < data->reference_count; count++ ) { char * object_id; asprintf(&object_id, "%p", data->references[count]); pack_string(pk, object_id); free(object_id); } free(data->references); } // Key4 : "file" pack_string(pk, "file"); // Value4 : File path where object is defined pack_string(pk, data->file); // Key5 : "line" pack_string(pk, "line"); // Value5 : Line no where object is defined if(data->line == 0) msgpack_pack_nil(pk); else msgpack_pack_unsigned_long(pk, data->line); // Key6 : "size" pack_string(pk, "size"); // Value6 : Size of the object in memory if(data->size == 0) msgpack_pack_nil(pk); else msgpack_pack_uint32(pk, data->size); } rbkit_object_dump_page * prev = page; page = page->next; free(prev); } // Send packed over zmq (buffer); //Cleanup free(dump); msgpack_sbuffer_free(buffer); msgpack_packer_free(pk); return Qnil; } |
.start_profiling(pub_port = nil, request_port = nil) ⇒ Object
Starts the server and enables memory profiling tracepoints
77 78 79 80 81 82 83 |
# File 'lib/rbkit.rb', line 77 def self.start_profiling(pub_port = nil, request_port = nil) @profiler = Rbkit::Profiler.new(pub_port, request_port) @profiler.start_server(enable_profiling: true) at_exit do self.stop_server end end |
.start_server(pub_port = nil, request_port = nil) ⇒ Object
Just starts the server and waits for instructions. The client needs to connect to the request_port and send commands over the wire. The client also needs to connect to the pub_port and subscribe to the responses from the server.
89 90 91 92 93 94 95 |
# File 'lib/rbkit.rb', line 89 def self.start_server(pub_port = nil, request_port = nil) @profiler = Rbkit::Profiler.new(pub_port, request_port) @profiler.start_server at_exit do self.stop_server end end |
.start_stat_server(*args) ⇒ Object
237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 |
# File 'ext/rbkit_tracer.c', line 237 static VALUE start_stat_server(int argc, VALUE *argv, VALUE self) { int default_pub_port = 5555; int default_request_port = 5556; VALUE pub_port; VALUE request_port; int bind_result; rb_scan_args(argc, argv, "02", &pub_port, &request_port); if (!NIL_P(pub_port)) { default_pub_port = FIX2INT(pub_port); if (default_pub_port < 1024 || default_pub_port > 65000) rb_raise(rb_eArgError, "invalid port value"); } if (!NIL_P(request_port)) { default_request_port = FIX2INT(request_port); if(default_request_port < 1024 || default_request_port > 65000) rb_raise(rb_eArgError, "invalid port value"); } // Creates a list which aggregates (); 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(); char zmq_endpoint[14]; sprintf(zmq_endpoint, "tcp://*:%d", default_pub_port); zmq_context = zmq_ctx_new(); zmq_publisher = zmq_socket(zmq_context, ZMQ_PUB); bind_result = zmq_bind(zmq_publisher, zmq_endpoint); assert(bind_result == 0); char zmq_request_endpoint[14]; sprintf(zmq_request_endpoint, "tcp://*:%d", default_request_port); zmq_response_socket = zmq_socket(zmq_context, ZMQ_REP); bind_result = zmq_bind(zmq_response_socket, zmq_request_endpoint); assert(bind_result == 0); items[0].socket = zmq_response_socket; items[0].events = ZMQ_POLLIN; return Qnil; } |
.start_stat_tracing ⇒ Object
438 439 440 441 442 443 444 445 446 447 448 449 |
# File 'ext/rbkit_tracer.c', line 438 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; } |
.stop_server ⇒ Object
Stops profiling and brings down the rbkit server if it’s running
98 99 100 |
# File 'lib/rbkit.rb', line 98 def self.stop_server @profiler.make_clean_exit end |
.stop_stat_server ⇒ Object
350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 |
# File 'ext/rbkit_tracer.c', line 350 static VALUE stop_stat_server() { if (logger->enabled == Qtrue) stop_stat_tracing(); // Destroy the list which aggregates (); // 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); return Qnil; } |
.stop_stat_tracing ⇒ Object
324 325 326 327 328 329 330 331 332 333 334 335 336 337 |
# File 'ext/rbkit_tracer.c', line 324 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; } |