rbkit 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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