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,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 9c98d007ffcab15624f4463ba9220cfe0b02635f
4
+ data.tar.gz: 4de1af44a5313d96dc359dac2e5929616c8362af
5
+ SHA512:
6
+ metadata.gz: 3b867812d99bcc5b41da934789e26f0053419757928db46d9f23f0faaac30757ef1eec6083d3b28e21277d99f5b8d4cf0e566fffc89c80b790005916492689f4
7
+ data.tar.gz: 001c0549d008515fc411499c94b4fe72768d801e1040ff44ab39e1ee0e79f7830de0aa3816be738a90a66aff728b2c34c9630a3e27231a163aee06af8200a09f
@@ -0,0 +1,3 @@
1
+ ---
2
+ BUNDLE_PATH: vendor/
3
+ BUNDLE_DISABLE_SHARED_GEMS: '1'
@@ -0,0 +1,16 @@
1
+ /vendor/ruby/
2
+ /ext/Makefile
3
+ /ext/mkmf.log
4
+ /ext/rbkit_tracer.bundle
5
+ /ext/*.o
6
+ /lib/rbkit_tracer.bundle
7
+ /tmp
8
+ Gemfile.lock
9
+ *.so
10
+ *.gem
11
+ .ruby-version
12
+ /ext/.kdev4/
13
+ /ext/ext.kdev4
14
+ /mkmf.log
15
+ /coverage
16
+ *.xcodeproj
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "rbczmq"
4
+ gem "msgpack"
5
+ gem "rake-compiler"
6
+
7
+ gemspec
@@ -0,0 +1,91 @@
1
+ Rbkit
2
+ =====
3
+
4
+ `rbkit` is a Ruby gem that plugs into your ruby process, taps profiling data
5
+ in realtime and sends it across the wire to the [rbkit-client](https://github.com/code-mancers/rbkit-client)
6
+ as packed messages.
7
+
8
+ ## Usage
9
+
10
+ Rbkit is not ready for production yet. To use the development version of Rbkit
11
+ in your Ruby project, follow the instructions under `Development` section and
12
+ then follow these steps :
13
+
14
+ #### Add `rbkit` to Gemfile
15
+
16
+ Add the following to the project's Gemfiles
17
+
18
+ ```
19
+ gem 'rbkit', path: <RBKIT_PATH>`
20
+ ```
21
+ and run `bundle install`
22
+
23
+ #### Inject `rbkit` into code
24
+
25
+ Wherever you want to start profiling, add the following :
26
+ ```
27
+ require 'rbkit'
28
+ Rbkit.start_profiling
29
+ ```
30
+ If using Rails, and you want to measure everything from the boot process,
31
+ a good place to put this would be at the end of `config/boot.rb`.
32
+
33
+ ## Development
34
+
35
+ #### Install zmq and msgpack
36
+
37
+ On OSX - Using `homebrew` following command should suffice:
38
+
39
+ ```
40
+ ~> brew install zeromq
41
+ ~> brew install msgpack
42
+ ```
43
+
44
+ On Linux - we recommend to download these libraries
45
+ from their respective home pages and manually compiling
46
+ and installing.
47
+
48
+ At some point, we will bundle these two C libraries during gem installations
49
+ but for now, this has to suffice.
50
+
51
+ #### Clone the repo
52
+
53
+ `git clone git@github.com:code-mancers/rbkit.git`
54
+
55
+ We'll call this `<RBKIT_PATH>`.
56
+
57
+ #### Set RBKIT_DEV environment flag
58
+
59
+ Set the environment variable `RBKIT_DEV` to true.
60
+ If using bash, put `export RBKIT_DEV=true` in your `~/.bashrc`.
61
+
62
+ This compiles the C extension with debug flag and also sets a macro named
63
+ `RBKIT_DEV` inside the C extension.
64
+
65
+ #### Compile the C extension
66
+
67
+ Two ways to do this :
68
+
69
+ ##### Using rake-compiler
70
+
71
+ ```
72
+ cd <RBKIT_PATH>
73
+ bundle install
74
+ bundle exec rake compile
75
+
76
+ ```
77
+
78
+ ##### Or do it manually
79
+
80
+ ```
81
+ cd <RBKIT_PATH/ext>
82
+ ruby extconf.rb
83
+ make
84
+ # Create a symlink at `lib/rbkit_tracer.bundle`
85
+ # that points to `ext/rbkit_tracer.bundle`
86
+ # (in order to use `rbkit` gem in Gemfiles using `path` option)
87
+ ```
88
+
89
+ ## TODO
90
+
91
+ TODOs are tracked as github issues.
@@ -0,0 +1,7 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ require 'rake/extensiontask'
4
+
5
+ Rake::ExtensionTask.new('rbkit_tracer') do |ext|
6
+ ext.ext_dir = 'ext'
7
+ end
@@ -0,0 +1,27 @@
1
+ ### How to debug a extension coming from C extension ###
2
+
3
+ 1. Build a Ruby which is compiled with debug symbols:
4
+
5
+ ./configure --prefix="$HOME/.rbenv/versions/debug_ruby" --enable-shared --disable-install-doc debugflags="-g" --with-opt-dir="$(brew --prefix openssl):$(brew --prefix libyaml):$(brew --prefix gdbm):$(brew --prefix libffi)"
6
+
7
+ I used above configure command to compile a debug symbol enabled Ruby.
8
+
9
+ 2. Build your extension with debug enabled.
10
+
11
+ 1. delete existing Makefile and object/bundle/so files.
12
+ 2. export CFLAGS=-g
13
+ 3. ruby extconf.rb
14
+ 4. make
15
+
16
+ 3. Run your program that makes use of C extension with:
17
+
18
+ ~> lldb /Users/gnufied/.rbenv/versions/debug_ruby/bin/ruby -> needs absolute path
19
+ lldb> process launch -- experiments/using_rbkit.rb
20
+
21
+ 4. LLDB is slightly different from `GDB` and more information about it can be found on,
22
+ http://lldb.llvm.org/tutorial.html . I specially found following commands useful:
23
+
24
+ 1. expr
25
+ 2. frame variable
26
+ 3. frame variable <variable_name>
27
+
@@ -0,0 +1,3 @@
1
+ ## Design of Rbkit profiler ##
2
+
3
+ 1.
@@ -0,0 +1,37 @@
1
+ $:<< File.join(File.dirname(__FILE__), "../lib")
2
+ $:<< File.join(File.dirname(__FILE__), "../ext")
3
+
4
+ require 'benchmark'
5
+ require 'rbkit'
6
+
7
+
8
+ def do_stuff
9
+ hash = {}
10
+ 10_00_000.times do |i|
11
+ hash[:"key#{i}"] = "value#{i}"
12
+ end
13
+ end
14
+
15
+ Benchmark.bm do |bm|
16
+ bm.report('Running code without Rbkit :') do
17
+ do_stuff
18
+ end
19
+
20
+ Rbkit.start_profiling
21
+ bm.report('Running code with Rbkit tracing :') do
22
+ do_stuff
23
+ end
24
+
25
+ bm.report('Time taken for objectspace snapshot :') do
26
+ Rbkit.send_objectspace_dump
27
+ end
28
+
29
+ bm.report('Running code after objectspace snapshot :') do
30
+ do_stuff
31
+ end
32
+
33
+ Rbkit.stop_server
34
+ bm.report('Running code after disabling rbkit :') do
35
+ do_stuff
36
+ end
37
+ end
@@ -0,0 +1,10 @@
1
+ require 'msgpack'
2
+
3
+ message = {
4
+ 'event_type' => 'gc_start',
5
+ 'timestamp' => Time.now.to_f
6
+ }
7
+
8
+ File.open("/tmp/msgpack.dat", "w") do |fl|
9
+ fl.write(message.to_msgpack)
10
+ end
@@ -0,0 +1,20 @@
1
+ $:<< File.join(File.dirname(__FILE__), "../lib")
2
+ $:<< File.join(File.dirname(__FILE__), "../ext")
3
+
4
+ require 'rbkit'
5
+
6
+ Rbkit.start_profiling(5555)
7
+
8
+ class Foo
9
+ def initialize(name)
10
+ @name = name
11
+ end
12
+ end
13
+
14
+ stuff = {}
15
+ 100.times do |i|
16
+ foo = Foo.new("hemant-#{i}")
17
+ stuff["name#{i}"] = "hemant-#{i}"
18
+ end
19
+
20
+ gets
@@ -0,0 +1,21 @@
1
+ $:<< File.join(File.dirname(__FILE__), "../lib")
2
+ $:<< File.join(File.dirname(__FILE__), "../ext")
3
+
4
+ require 'rbkit'
5
+
6
+ Rbkit.start_profiling(5555)
7
+
8
+ class Foo
9
+ def initialize(name)
10
+ @name = name
11
+ end
12
+ end
13
+
14
+ stuff = {}
15
+ 100.times do |i|
16
+ sleep 0.01
17
+ foo = Foo.new("hemant-#{i}")
18
+ stuff["name#{i}"] = "hemant-#{i}"
19
+ end
20
+
21
+ Rbkit.dump_objects
@@ -0,0 +1,25 @@
1
+ # encoding: utf-8
2
+ # To use this client install following gems
3
+ # gem install msgpack
4
+ # gem install rbczmq
5
+
6
+ require 'zmq'
7
+ require 'pp'
8
+ require "msgpack"
9
+
10
+ # PUB / SUB topology
11
+
12
+ Thread.abort_on_exception = true
13
+ fl = File.open("foo.dat", "w")
14
+
15
+ ctx = ZMQ::Context.new
16
+ socket = ctx.socket(:SUB)
17
+ socket.verbose = true
18
+ socket.subscribe("")
19
+ socket.connect("tcp://localhost:5555")
20
+ loop do
21
+ message = socket.recv
22
+ unpacked_message = MessagePack.unpack(message)
23
+ p unpacked_message
24
+ end
25
+ fl.close()
@@ -0,0 +1,54 @@
1
+ require 'zmq'
2
+ require 'msgpack'
3
+ require 'pp'
4
+
5
+ Thread.abort_on_exception = true
6
+
7
+
8
+ commands = [
9
+ 'start_memory_profile',
10
+ 'stop_memory_profile',
11
+ 'objectspace_snapshot',
12
+ 'trigger_gc'
13
+ ]
14
+
15
+ output_file = File.open("/tmp/rbkit.log", "w")
16
+ puts "Writing output to file #{output_file.path}"
17
+ ctx = ZMQ::Context.new
18
+
19
+ puts "Enter IPv4 address of Rbkit server. (Blank for localhost) :"
20
+ server_ip = gets.strip
21
+ server_ip = "127.0.0.1" if server_ip.empty?
22
+
23
+ Thread.new do
24
+ request_socket = ctx.socket(:REQ)
25
+ request_socket.connect("tcp://#{server_ip}:5556")
26
+ loop do
27
+ puts "Available commands :"
28
+ commands.each_with_index do |c, i|
29
+ puts "#{i+1}. #{c}"
30
+ end
31
+ command = commands[gets.strip.to_i - 1] rescue ''
32
+ unless command.empty?
33
+ request_socket.send(command)
34
+ puts "sent #{command}"
35
+ response = request_socket.recv()
36
+ puts "received #{response}"
37
+ end
38
+ end
39
+ end
40
+
41
+ socket = ctx.socket(:SUB)
42
+ socket.subscribe("")
43
+ socket.connect("tcp://#{server_ip}:5555")
44
+
45
+ begin
46
+ loop do
47
+ message = socket.recv
48
+ unpacked_message = MessagePack.unpack(message)
49
+ PP.pp(unpacked_message, output_file)
50
+ output_file.flush
51
+ end
52
+ ensure
53
+ output_file.close
54
+ end
@@ -0,0 +1,22 @@
1
+ require 'zmq'
2
+ require 'pp'
3
+ require "msgpack"
4
+
5
+ Thread.abort_on_exception = true
6
+
7
+ ctx = ZMQ::Context.new
8
+ socket = ctx.socket(:SUB)
9
+ socket.subscribe("")
10
+ socket.connect("tcp://127.0.0.1:5555")
11
+
12
+ request_socket = ctx.socket(:REQ)
13
+ request_socket.connect("tcp://127.0.0.1:5556")
14
+ request_socket.send("start_memory_profile")
15
+ response = request_socket.recv()
16
+ puts "received #{response}"
17
+
18
+ loop do
19
+ message = socket.recv
20
+ unpacked_message = MessagePack.unpack(message)
21
+ p unpacked_message
22
+ end
@@ -0,0 +1,11 @@
1
+ class Foo
2
+ def initialize
3
+ @names = {}
4
+ end
5
+
6
+ def run
7
+ 1000.times do |i|
8
+ @names[i] = "allocating #{i}"
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,19 @@
1
+ $:<< File.join(File.dirname(__FILE__), "../lib")
2
+ $:<< File.join(File.dirname(__FILE__), "../ext")
3
+
4
+ require 'rbkit'
5
+
6
+ Rbkit.start_profiling(5555)
7
+
8
+ class Foo
9
+ def initialize(name)
10
+ @name = name
11
+ end
12
+ end
13
+
14
+ stuff = {}
15
+ 10_00_0000.times do |i|
16
+ sleep 0.01
17
+ foo = Foo.new("hemant-#{i}")
18
+ stuff["name#{i}"] = "hemant-#{i}"
19
+ end
@@ -0,0 +1,46 @@
1
+ require "zmq"
2
+ require "pp"
3
+
4
+ $ctx = ZMQ::Context.new
5
+
6
+ ENDPOINT = "tcp://127.0.0.1:5555"
7
+ Thread.abort_on_exception = true
8
+
9
+ class Client
10
+ @@publish_topic = "bar"
11
+
12
+ def start_publisher
13
+ pub_socket = $ctx.socket(:PUB)
14
+ pub_socket.verbose = true
15
+ pub_socket.connect(ENDPOINT)
16
+ loop do
17
+ pub_socket.send("#{@@publish_topic} client#{Time.now}")
18
+ sleep(1)
19
+ end
20
+ end
21
+
22
+ def start_subscriber
23
+ sub_socket = $ctx.socket(:SUB)
24
+ # sub_socket.verbose = true
25
+ sub_socket.subscribe("foo")
26
+ sub_socket.connect(ENDPOINT)
27
+ loop do
28
+ data = sub_socket.recv
29
+ puts "********** Received from server #{data}"
30
+ end
31
+ end
32
+ end
33
+
34
+
35
+ client = Client.new()
36
+ threads = []
37
+
38
+ threads << Thread.new do
39
+ client.start_publisher
40
+ end
41
+
42
+ threads << Thread.new do
43
+ client.start_subscriber
44
+ end
45
+
46
+ threads.each { |thr| thr.join }