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.
- checksums.yaml +7 -0
- data/.bundle/config +3 -0
- data/.gitignore +16 -0
- data/Gemfile +7 -0
- data/README.md +91 -0
- data/Rakefile +7 -0
- data/docs/debugging.md +27 -0
- data/docs/design.md +3 -0
- data/experiments/benchmark.rb +37 -0
- data/experiments/mspack_to_file.rb +10 -0
- data/experiments/no_growth.rb +20 -0
- data/experiments/object_dump.rb +21 -0
- data/experiments/rbkit_client.rb +25 -0
- data/experiments/rbkit_command_test.rb +54 -0
- data/experiments/using_new_client.rb +22 -0
- data/experiments/using_object_tracer.rb +11 -0
- data/experiments/using_rbkit.rb +19 -0
- data/experiments/zmq_client.rb +46 -0
- data/experiments/zmq_server.rb +52 -0
- data/ext/extconf.rb +18 -0
- data/ext/rbkit_message_aggregator.c +66 -0
- data/ext/rbkit_message_aggregator.h +13 -0
- data/ext/rbkit_object_graph.c +154 -0
- data/ext/rbkit_object_graph.h +39 -0
- data/ext/rbkit_tracer.c +583 -0
- data/ext/rbkit_tracer.h +35 -0
- data/lib/rbkit.rb +101 -0
- data/lib/rbkit/timer.rb +18 -0
- data/lib/rbkit/version.rb +3 -0
- data/rbkit.gemspec +33 -0
- data/schema/tracing_info.md +8 -0
- data/spec/spec_helper.rb +15 -0
- metadata +120 -0
checksums.yaml
ADDED
@@ -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
|
data/.bundle/config
ADDED
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -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.
|
data/Rakefile
ADDED
data/docs/debugging.md
ADDED
@@ -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
|
+
|
data/docs/design.md
ADDED
@@ -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,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,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 }
|