rbkit 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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 }