rbkit 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,35 @@
1
+ #ifndef RBKIT_TRACER_H
2
+ #define RBKIT_TRACER_H
3
+
4
+ #include "ruby/ruby.h"
5
+ #include "ruby/debug.h"
6
+ #include <stdio.h>
7
+ #include <assert.h>
8
+ #include "zmq.h"
9
+ #include "msgpack.h"
10
+
11
+ // Structure is used to store profiling data
12
+ struct gc_hooks {
13
+ VALUE hooks[3];
14
+ VALUE enabled;
15
+ void (*funcs[3])(void *data, int event_index);
16
+ void *args[3];
17
+ void *data;
18
+ st_table *object_table;
19
+ st_table *str_table;
20
+ VALUE newobj_trace;
21
+ VALUE freeobj_trace;
22
+ int keep_remains;
23
+ msgpack_sbuffer *sbuf;
24
+ msgpack_packer *msgpacker;
25
+ };
26
+
27
+ char * tracer_string_recv(void *socket);
28
+ int tracer_string_send(void *socket, const char *message);
29
+ void pack_value_object(msgpack_packer *packer, VALUE value);
30
+ void pack_string(msgpack_packer *packer, char *string);
31
+ void pack_timestamp(msgpack_packer *packer);
32
+ void pack_event_header(msgpack_packer *packer, const char *event_type, int map_size);
33
+ void pack_pointer(msgpack_packer *packer, VALUE object_id);
34
+
35
+ #endif
@@ -0,0 +1,101 @@
1
+ require "rbkit_tracer"
2
+ require "rbkit/timer"
3
+ require "objspace"
4
+
5
+ # Class implements user friendly interface in pure Ruby for profiler.
6
+ module Rbkit
7
+ class Profiler
8
+ attr_accessor :pub_port, :request_port
9
+
10
+ def initialize(pub_port, request_port)
11
+ @pub_port = pub_port
12
+ @request_port = request_port
13
+ @profiler_thread = nil
14
+ @stop_thread = false
15
+ @server_running = false
16
+ @gc_stats_timer = Rbkit::Timer.new(5) do
17
+ data = GC.stat
18
+ no_of_allocated_pages = data[:heap_length]
19
+ max_objects_per_page = GC::INTERNAL_CONSTANTS[:HEAP_OBJ_LIMIT]
20
+ size_of_one_obj = GC::INTERNAL_CONSTANTS[:RVALUE_SIZE]
21
+ data[:total_heap_size] = no_of_allocated_pages * max_objects_per_page *
22
+ size_of_one_obj
23
+ data[:total_memsize] = ObjectSpace.memsize_of_all
24
+ Rbkit.send_hash_as_event(data, "gc_stats")
25
+ end
26
+ @message_dispatch_timer = Rbkit::Timer.new(1) do
27
+ Rbkit.send_messages
28
+ end
29
+ end
30
+
31
+ def start_server(enable_profiling: false)
32
+ return if @server_running
33
+ @profiler_thread = Thread.new do
34
+ Rbkit.start_stat_server(pub_port, request_port)
35
+ Rbkit.start_stat_tracing if enable_profiling
36
+ loop do
37
+ break if @stop_thread
38
+ incoming_request = Rbkit.poll_for_request
39
+ process_incoming_request(incoming_request)
40
+ @gc_stats_timer.run
41
+ @message_dispatch_timer.run
42
+ # Let us sleep this thread for a bit, so as other things can run.
43
+ sleep(0.05)
44
+ end
45
+ end
46
+ @server_running = true
47
+ end
48
+
49
+ def process_incoming_request(incoming_request)
50
+ case incoming_request
51
+ when "start_memory_profile"
52
+ Rbkit.start_stat_tracing
53
+ when "stop_memory_profile"
54
+ Rbkit.stop_stat_tracing
55
+ when "trigger_gc"
56
+ GC.start
57
+ when "objectspace_snapshot"
58
+ Rbkit.send_objectspace_dump
59
+ end
60
+ end
61
+
62
+ def stop_server
63
+ return if !@server_running
64
+ Rbkit.stop_stat_server
65
+ @server_running = false
66
+ end
67
+
68
+ def make_clean_exit
69
+ @stop_thread = true
70
+ stop_server
71
+ end
72
+ end
73
+
74
+ ########### Rbkit API ###########
75
+
76
+ # Starts the server and enables memory profiling tracepoints
77
+ def self.start_profiling(pub_port = nil, request_port = nil)
78
+ @profiler = Rbkit::Profiler.new(pub_port, request_port)
79
+ @profiler.start_server(enable_profiling: true)
80
+ at_exit do
81
+ self.stop_server
82
+ end
83
+ end
84
+
85
+ # Just starts the server and waits for instructions.
86
+ # The client needs to connect to the request_port and send
87
+ # commands over the wire. The client also needs to connect
88
+ # to the pub_port and subscribe to the responses from the server.
89
+ def self.start_server(pub_port = nil, request_port = nil)
90
+ @profiler = Rbkit::Profiler.new(pub_port, request_port)
91
+ @profiler.start_server
92
+ at_exit do
93
+ self.stop_server
94
+ end
95
+ end
96
+
97
+ # Stops profiling and brings down the rbkit server if it's running
98
+ def self.stop_server
99
+ @profiler.make_clean_exit
100
+ end
101
+ end
@@ -0,0 +1,18 @@
1
+ module Rbkit
2
+ class Timer
3
+ attr_accessor :last_fired_at, :interval
4
+
5
+ def initialize(interval, &timer_block)
6
+ @interval = interval
7
+ @timer_block = timer_block
8
+ @last_fired_at = Time.now
9
+ end
10
+
11
+ def run
12
+ if Time.now - last_fired_at > interval
13
+ @timer_block.call
14
+ @last_fired_at = Time.now
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,3 @@
1
+ module Rbkit
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,33 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ GEM_NAME = "rbkit"
4
+
5
+ lib = File.expand_path("../lib", __FILE__)
6
+ $: << lib unless $:.include?(lib)
7
+
8
+ require "rbkit/version"
9
+
10
+ Gem::Specification.new do |s|
11
+ s.name = GEM_NAME
12
+ s.version = Rbkit::VERSION
13
+
14
+ if s.respond_to? :required_rubygems_version=
15
+ s.required_rubygems_version = Gem::Requirement.new(">= 0")
16
+ end
17
+ s.authors = ["Hemant Kumar", "Emil Soman", "Kashyap"]
18
+ s.description = %q{Something small for process management}
19
+ s.email = %q{hemant@codemancers.com emil@codemancers.com kashyap@codemancers.com}
20
+
21
+ s.files = `git ls-files`.split("\n")
22
+ s.test_files = `git ls-files -- {spec,features}/*`.split("\n")
23
+ s.extensions = 'ext/extconf.rb'
24
+ s.require_paths = ["lib"]
25
+
26
+ s.homepage = %q{http://rbkit.codemancers.com}
27
+ s.licenses = ["MIT"]
28
+ s.require_paths = ["lib"]
29
+ s.summary = %q{Ruby profiler for rest of us}
30
+ s.add_development_dependency("rspec")
31
+ s.add_development_dependency("rake")
32
+ s.add_development_dependency("simplecov")
33
+ end
@@ -0,0 +1,8 @@
1
+ ## How we send tracing information ##
2
+
3
+ 1. For now Tracing information is sent via simple strings like:
4
+
5
+ obj_created <klass_name> <object_id_in_hex>
6
+ obj_destroyed <klass_name> <object_id_in_hex>
7
+ gc_start
8
+ gc_end_s
@@ -0,0 +1,15 @@
1
+ require "pry"
2
+ require "simplecov"
3
+ SimpleCov.start do
4
+ add_filter "/spec/"
5
+ end
6
+
7
+ RSpec.configure do |config|
8
+ config.run_all_when_everything_filtered = true
9
+ config.filter_run :focus
10
+ # Run specs in random order to surface order dependencies. If you find an
11
+ # order dependency and want to debug it, you can fix the order by providing
12
+ # the seed, which is printed after each run.
13
+ # --seed 1234
14
+ config.order = 'random'
15
+ end
metadata ADDED
@@ -0,0 +1,120 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rbkit
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Hemant Kumar
8
+ - Emil Soman
9
+ - Kashyap
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2014-09-21 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rspec
17
+ requirement: !ruby/object:Gem::Requirement
18
+ requirements:
19
+ - - ">="
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ version: '0'
29
+ - !ruby/object:Gem::Dependency
30
+ name: rake
31
+ requirement: !ruby/object:Gem::Requirement
32
+ requirements:
33
+ - - ">="
34
+ - !ruby/object:Gem::Version
35
+ version: '0'
36
+ type: :development
37
+ prerelease: false
38
+ version_requirements: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: '0'
43
+ - !ruby/object:Gem::Dependency
44
+ name: simplecov
45
+ requirement: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: '0'
50
+ type: :development
51
+ prerelease: false
52
+ version_requirements: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ description: Something small for process management
58
+ email: hemant@codemancers.com emil@codemancers.com kashyap@codemancers.com
59
+ executables: []
60
+ extensions:
61
+ - ext/extconf.rb
62
+ extra_rdoc_files: []
63
+ files:
64
+ - ".bundle/config"
65
+ - ".gitignore"
66
+ - Gemfile
67
+ - README.md
68
+ - Rakefile
69
+ - docs/debugging.md
70
+ - docs/design.md
71
+ - experiments/benchmark.rb
72
+ - experiments/mspack_to_file.rb
73
+ - experiments/no_growth.rb
74
+ - experiments/object_dump.rb
75
+ - experiments/rbkit_client.rb
76
+ - experiments/rbkit_command_test.rb
77
+ - experiments/using_new_client.rb
78
+ - experiments/using_object_tracer.rb
79
+ - experiments/using_rbkit.rb
80
+ - experiments/zmq_client.rb
81
+ - experiments/zmq_server.rb
82
+ - ext/extconf.rb
83
+ - ext/rbkit_message_aggregator.c
84
+ - ext/rbkit_message_aggregator.h
85
+ - ext/rbkit_object_graph.c
86
+ - ext/rbkit_object_graph.h
87
+ - ext/rbkit_tracer.c
88
+ - ext/rbkit_tracer.h
89
+ - lib/rbkit.rb
90
+ - lib/rbkit/timer.rb
91
+ - lib/rbkit/version.rb
92
+ - rbkit.gemspec
93
+ - schema/tracing_info.md
94
+ - spec/spec_helper.rb
95
+ homepage: http://rbkit.codemancers.com
96
+ licenses:
97
+ - MIT
98
+ metadata: {}
99
+ post_install_message:
100
+ rdoc_options: []
101
+ require_paths:
102
+ - lib
103
+ required_ruby_version: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ required_rubygems_version: !ruby/object:Gem::Requirement
109
+ requirements:
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ version: '0'
113
+ requirements: []
114
+ rubyforge_project:
115
+ rubygems_version: 2.2.2
116
+ signing_key:
117
+ specification_version: 4
118
+ summary: Ruby profiler for rest of us
119
+ test_files:
120
+ - spec/spec_helper.rb