rbkit 0.0.1 → 0.1.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +5 -0
- data/.rspec +2 -0
- data/.travis.yml +17 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +6 -2
- data/LICENSE.txt +22 -0
- data/README.md +74 -11
- data/Rakefile +27 -3
- data/docs/EVENT_FORMAT.md +195 -0
- data/experiments/object_dump.rb +1 -1
- data/experiments/rbkit_command_test.rb +3 -1
- data/experiments/using_rbkit.rb +1 -1
- data/ext/extconf.rb +95 -12
- data/ext/rbkit_allocation_info.c +91 -0
- data/ext/rbkit_allocation_info.h +17 -0
- data/ext/rbkit_event.c +71 -0
- data/ext/rbkit_event.h +63 -0
- data/ext/rbkit_event_packer.c +251 -0
- data/ext/rbkit_event_packer.h +23 -0
- data/ext/rbkit_message_aggregator.c +9 -16
- data/ext/rbkit_message_aggregator.h +0 -1
- data/ext/rbkit_object_graph.c +6 -49
- data/ext/rbkit_object_graph.h +12 -3
- data/ext/rbkit_test_helper.c +25 -0
- data/ext/rbkit_test_helper.h +1 -0
- data/ext/rbkit_tracer.c +106 -323
- data/ext/rbkit_tracer.h +2 -10
- data/lib/rbkit.rb +57 -35
- data/lib/rbkit/rbkit_gc.rb +79 -0
- data/lib/rbkit/version.rb +1 -1
- data/logo.png +0 -0
- data/rbkit.gemspec +1 -0
- data/setup.rb +37 -0
- data/spec/gc_stat_spec.rb +31 -0
- data/spec/hash_event_spec.rb +29 -0
- data/spec/obj_created_spec.rb +52 -0
- data/spec/obj_destroyed_spec.rb +44 -0
- data/spec/object_space_dump_spec.rb +77 -0
- data/spec/rbkit_helpful_messages_spec.rb +61 -0
- data/spec/spec_helper.rb +11 -6
- data/spec/start_server_spec.rb +29 -0
- data/spec/status_spec.rb +48 -0
- data/spec/support/foo_bar_sample_class.rb +24 -0
- data/spec/support/have_message_matcher.rb +26 -0
- metadata +40 -4
- data/schema/tracing_info.md +0 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 739b3af12258b89ecfdae05d06c03889329d496d
|
4
|
+
data.tar.gz: c7144822b77d0173352ef6c184c7c8ddaa046311
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b46dc7d9c12bd100c59177e0afc0d0021ede93328d4e5444f4cbefac70bfd960046f88e20ebd4aa2cdde458a9a9caa01f5e9697a4a8e542e43df7840476f7889
|
7
|
+
data.tar.gz: d8e462c46b173086ce21f04d1350ebdaae5023a6da9407c50841a2dfb8755d2b281908450136db079570a3ab3ea6f53789039e5391ad3bf30cf51406407f51fa
|
data/.gitignore
CHANGED
data/.rspec
ADDED
data/.travis.yml
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
language: ruby
|
2
|
+
bundler_args: "--without exclude_in_travis"
|
3
|
+
rvm:
|
4
|
+
- 2.1.3
|
5
|
+
- 2.2.0
|
6
|
+
- ruby-head
|
7
|
+
os:
|
8
|
+
- linux
|
9
|
+
- osx
|
10
|
+
script: bundle exec rake run_spec
|
11
|
+
notifications:
|
12
|
+
hipchat:
|
13
|
+
rooms:
|
14
|
+
secure: KdhzB9VueLEJp9p/ZUFaXAMO0u1CEbT0sjdRt10jqseAJCld9CAK1KAb1f/mNO/+cbVd+7W9UdHA0cEGUZ9dLP9Mcpmy31QxOJSITUCrRiLOF1ti13Lq4WHpMM46Tz6p7vVYd4zpPj9Mup+lCTGOeCovReX+neIoZw0UjDg9oGs=
|
15
|
+
template:
|
16
|
+
- '%{result}: %{repository_slug}#%{branch} - <a href="%{compare_url}">%{commit}</a>(%{commit_message}) by %{author} (<a href="%{build_url}">Details</a>)'
|
17
|
+
format: html
|
data/CHANGELOG.md
ADDED
data/Gemfile
CHANGED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2014 Emil Soman, Hemant Kumar
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
CHANGED
@@ -1,5 +1,8 @@
|
|
1
|
-
Rbkit
|
2
|
-
|
1
|
+
<img src="./logo.png" height="30px" /> Rbkit
|
2
|
+
============================================
|
3
|
+
|
4
|
+
[![Gem Version](https://badge.fury.io/rb/rbkit.svg)](http://badge.fury.io/rb/rbkit)
|
5
|
+
[![Build Status](https://travis-ci.org/code-mancers/rbkit.svg?branch=tests)](https://travis-ci.org/code-mancers/rbkit)
|
3
6
|
|
4
7
|
`rbkit` is a Ruby gem that plugs into your ruby process, taps profiling data
|
5
8
|
in realtime and sends it across the wire to the [rbkit-client](https://github.com/code-mancers/rbkit-client)
|
@@ -16,24 +19,87 @@ then follow these steps :
|
|
16
19
|
Add the following to the project's Gemfiles
|
17
20
|
|
18
21
|
```
|
19
|
-
gem 'rbkit', path: <RBKIT_PATH
|
22
|
+
gem 'rbkit', path: <RBKIT_PATH>
|
20
23
|
```
|
24
|
+
|
25
|
+
|
21
26
|
and run `bundle install`
|
22
27
|
|
28
|
+
#### Installation without Rubygems
|
29
|
+
|
30
|
+
You can also install `rbkit` without bundler/rubygems. This can
|
31
|
+
be useful, if you are profiling a Ruby app where you want to measure
|
32
|
+
overhead of Rubygems/Bundler.
|
33
|
+
|
34
|
+
Just clone the repository or download from a release tag and run:
|
35
|
+
|
36
|
+
```
|
37
|
+
# Run from root of rbkit directory.
|
38
|
+
~> ruby setup.rb
|
39
|
+
```
|
40
|
+
|
41
|
+
This should install `rbkit`
|
42
|
+
in ruby's `site_dir` and then you don't need `rbkit` added to your
|
43
|
+
`Gemfile` for requiring `rbkit`.
|
44
|
+
|
23
45
|
#### Inject `rbkit` into code
|
24
46
|
|
25
47
|
Wherever you want to start profiling, add the following :
|
48
|
+
|
49
|
+
```ruby
|
50
|
+
require 'rbkit' # Not needed in Rails
|
51
|
+
Rbkit.start_server
|
26
52
|
```
|
27
|
-
|
28
|
-
Rbkit.start_profiling
|
29
|
-
```
|
53
|
+
|
30
54
|
If using Rails, and you want to measure everything from the boot process,
|
31
55
|
a good place to put this would be at the end of `config/boot.rb`.
|
32
56
|
|
57
|
+
## Rbkit API
|
58
|
+
|
59
|
+
### Rbkit.start_server(pub_port: nil, request_port: nil)
|
60
|
+
|
61
|
+
Starts the Rbkit server and waits for a client to connect and issue
|
62
|
+
commands to the request_port, until then there's zero performance overhead.
|
63
|
+
Profiling data is sent asynchronously over pub_port.
|
64
|
+
This method can be called early in a ruby application so that
|
65
|
+
whenever profiling needs to be done, the client can attach itself to the
|
66
|
+
inactive server, do the profiling and leave. Returns true if server was
|
67
|
+
started successfully.
|
68
|
+
|
69
|
+
|
70
|
+
|argument | valid values | default value | description |
|
71
|
+
|--------------|--------------|---------------|---------------------------------------------------|
|
72
|
+
|pub_port | nil, fixnum | nil | Override default message publishing port of 5555 |
|
73
|
+
|request_port | nil, fixnum | nil | Override default command listener port of 5556 |
|
74
|
+
|
75
|
+
|
76
|
+
### Rbkit.start_profiling(pub_port: nil, request_port: nil, enable_object_trace: true, enable_gc_stats: true)
|
77
|
+
|
78
|
+
Starts the server with all tracepoints enabled by default. User can
|
79
|
+
optionally disable tracepoints using the optional arguments.
|
80
|
+
This method can be used to profile the startup process of a ruby
|
81
|
+
application where sending commands from the client to enable
|
82
|
+
profiling is not feasible. Returns true if server was started successfully.
|
83
|
+
|
84
|
+
Arguments:
|
85
|
+
|
86
|
+
|argument | valid values | default value | description |
|
87
|
+
|---------------------|--------------|---------------|--------------------------------------------------|
|
88
|
+
|pub_port | nil, fixnum | nil | Override default message publishing port of 5555 |
|
89
|
+
|request_port | nil, fixnum | nil | Override default command listener port of 5556 |
|
90
|
+
|enable_object_trace | true/false | true | Enables object creation/deletion events |
|
91
|
+
|enable_gc_stats | true/false | true | Enables GC stats which is sent every 5 seconds |
|
92
|
+
|
93
|
+
|
33
94
|
## Development
|
34
95
|
|
35
96
|
#### Install zmq and msgpack
|
36
97
|
|
98
|
+
If zmq and msgpack are not installed, Rbkit automatically downloads
|
99
|
+
and installs the two libraries from source during gem installation.
|
100
|
+
But if you are developing Rbkit, it makes sense to have these
|
101
|
+
preinstalled:
|
102
|
+
|
37
103
|
On OSX - Using `homebrew` following command should suffice:
|
38
104
|
|
39
105
|
```
|
@@ -45,9 +111,6 @@ On Linux - we recommend to download these libraries
|
|
45
111
|
from their respective home pages and manually compiling
|
46
112
|
and installing.
|
47
113
|
|
48
|
-
At some point, we will bundle these two C libraries during gem installations
|
49
|
-
but for now, this has to suffice.
|
50
|
-
|
51
114
|
#### Clone the repo
|
52
115
|
|
53
116
|
`git clone git@github.com:code-mancers/rbkit.git`
|
@@ -66,7 +129,7 @@ This compiles the C extension with debug flag and also sets a macro named
|
|
66
129
|
|
67
130
|
Two ways to do this :
|
68
131
|
|
69
|
-
##### Using rake
|
132
|
+
##### Using rake
|
70
133
|
|
71
134
|
```
|
72
135
|
cd <RBKIT_PATH>
|
@@ -81,7 +144,7 @@ bundle exec rake compile
|
|
81
144
|
cd <RBKIT_PATH/ext>
|
82
145
|
ruby extconf.rb
|
83
146
|
make
|
84
|
-
# Create a symlink at `lib/rbkit_tracer.bundle`
|
147
|
+
# Create a symlink at `lib/rbkit_tracer.bundle` (or .so if on linux)
|
85
148
|
# that points to `ext/rbkit_tracer.bundle`
|
86
149
|
# (in order to use `rbkit` gem in Gemfiles using `path` option)
|
87
150
|
```
|
data/Rakefile
CHANGED
@@ -1,7 +1,31 @@
|
|
1
1
|
require "bundler/gem_tasks"
|
2
|
+
require "rspec/core/rake_task"
|
2
3
|
|
3
|
-
|
4
|
+
RSpec::Core::RakeTask.new
|
4
5
|
|
5
|
-
|
6
|
-
|
6
|
+
task :compile do
|
7
|
+
symlink_bundle_path = File.absolute_path "lib/rbkit_tracer.#{RbConfig::MAKEFILE_CONFIG['DLEXT']}"
|
8
|
+
original_bundle_path = File.absolute_path "ext/rbkit_tracer.#{RbConfig::MAKEFILE_CONFIG['DLEXT']}"
|
9
|
+
Dir.chdir 'ext' do
|
10
|
+
system("#{Gem.ruby} extconf.rb")
|
11
|
+
system("make")
|
12
|
+
File.delete(symlink_bundle_path) if File.symlink? symlink_bundle_path
|
13
|
+
File.symlink(original_bundle_path, symlink_bundle_path)
|
14
|
+
end
|
7
15
|
end
|
16
|
+
|
17
|
+
desc "Run each spec in isolated process"
|
18
|
+
task :run_spec => [:compile] do
|
19
|
+
command_output = []
|
20
|
+
Dir["spec/*_spec.rb"].each do |file|
|
21
|
+
puts "Running #{file}.."
|
22
|
+
command_output << system("bundle exec rspec #{file}")
|
23
|
+
end
|
24
|
+
if command_output.all?
|
25
|
+
exit(0)
|
26
|
+
else
|
27
|
+
exit(-1)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
task :default => [:compile, :spec]
|
@@ -0,0 +1,195 @@
|
|
1
|
+
Refer [issue #11](https://github.com/code-mancers/rbkit/issues/11) for some history.
|
2
|
+
|
3
|
+
## Event types
|
4
|
+
|
5
|
+
EventType is an integer value indicating the type of event
|
6
|
+
contained in the message. It's basically the following enum :
|
7
|
+
|
8
|
+
```c
|
9
|
+
enum EventType {
|
10
|
+
obj_created,
|
11
|
+
obj_destroyed,
|
12
|
+
gc_start,
|
13
|
+
gc_end_m,
|
14
|
+
gc_end_s,
|
15
|
+
object_space_dump,
|
16
|
+
gc_stats,
|
17
|
+
event_collection,
|
18
|
+
handshake
|
19
|
+
}
|
20
|
+
```
|
21
|
+
|
22
|
+
ie,
|
23
|
+
|
24
|
+
```ruby
|
25
|
+
# Rbkit::EVENT_TYPES
|
26
|
+
{
|
27
|
+
"obj_created" => 0,
|
28
|
+
"obj_destroyed" => 1,
|
29
|
+
"gc_start" => 2,
|
30
|
+
"gc_end_m" => 3,
|
31
|
+
"gc_end_s" => 4,
|
32
|
+
"object_space_dump" => 5,
|
33
|
+
"gc_stats" => 6,
|
34
|
+
"event_collection" => 7,
|
35
|
+
"handshake" => 8
|
36
|
+
}
|
37
|
+
```
|
38
|
+
|
39
|
+
The keys of all event message hashes are integer values whose enum names
|
40
|
+
are used below. `Rbkit::MESSAGE_FIELDS` gives you the exhaustive list of
|
41
|
+
enums used.
|
42
|
+
|
43
|
+
```ruby
|
44
|
+
# Rbkit::MESSAGE_FIELDS
|
45
|
+
{
|
46
|
+
'event_type' => 0,
|
47
|
+
'timestamp' => 1,
|
48
|
+
'payload' => 2,
|
49
|
+
'object_id' => 3,
|
50
|
+
'class_name' => 4,
|
51
|
+
'references' => 5,
|
52
|
+
'file' => 6,
|
53
|
+
'line' => 7,
|
54
|
+
'size' => 8,
|
55
|
+
'message_counter' => 9
|
56
|
+
}
|
57
|
+
```
|
58
|
+
|
59
|
+
## Message frames
|
60
|
+
|
61
|
+
Generic message frame is of the format :
|
62
|
+
|
63
|
+
```yaml
|
64
|
+
{
|
65
|
+
event_type: <EventType>,
|
66
|
+
timestamp: <timestamp in milliseconds>,
|
67
|
+
payload: <PAYLOAD> # Optional
|
68
|
+
}
|
69
|
+
```
|
70
|
+
|
71
|
+
### Message frame for event_collection :
|
72
|
+
|
73
|
+
All events are aggregated in the server and sent as the payload of a special
|
74
|
+
type of event named `event_collection`. The payload will be an array containing
|
75
|
+
other event messages.
|
76
|
+
|
77
|
+
```yaml
|
78
|
+
{
|
79
|
+
event_type: "event_collection",
|
80
|
+
message_counter: <incrementing counter>,
|
81
|
+
timestamp: <timestamp in milliseconds>,
|
82
|
+
payload: [
|
83
|
+
{event_type: <EVENT_TYPE>, timestamp: <TIMESTAMP>, payload: <PAYLOAD>},
|
84
|
+
{event_type: <EVENT_TYPE>, timestamp: <TIMESTAMP>, payload: <PAYLOAD>}
|
85
|
+
]
|
86
|
+
}
|
87
|
+
```
|
88
|
+
|
89
|
+
### Message frame for HANDSHAKE :
|
90
|
+
|
91
|
+
Handshake is a special message which is sent synchronously over the REQ-REP
|
92
|
+
socket pair and not on the PUB socket. When a "handshake" command is send by
|
93
|
+
the client, the server responses with the Rbkit status. The handshake reply
|
94
|
+
is of the following format :
|
95
|
+
|
96
|
+
```yaml
|
97
|
+
{
|
98
|
+
event_type: "handshake",
|
99
|
+
timestamp: <timestamp in milliseconds>,
|
100
|
+
payload: {
|
101
|
+
"process_name" => <Name of the process>,
|
102
|
+
"pwd" => <working directory of the app>,
|
103
|
+
"pid" => <PID of the ruby process>,
|
104
|
+
"object_trace_enabled" => <0 or 1>
|
105
|
+
}
|
106
|
+
}
|
107
|
+
```
|
108
|
+
|
109
|
+
### Message frame for NEW_OBJECT :
|
110
|
+
|
111
|
+
When the NEW_OBJECT event is triggered, the object id and the class name
|
112
|
+
are sent as the payload.
|
113
|
+
|
114
|
+
```yaml
|
115
|
+
{
|
116
|
+
event_type: obj_created,
|
117
|
+
timestamp: <timestamp in milliseconds>,
|
118
|
+
payload: {
|
119
|
+
object_id: <OBJECT_ID>,
|
120
|
+
class_name: <CLASS_NAME>
|
121
|
+
}
|
122
|
+
}
|
123
|
+
```
|
124
|
+
|
125
|
+
### Message frame for FREE_OBJECT :
|
126
|
+
|
127
|
+
```yaml
|
128
|
+
{
|
129
|
+
event_type: obj_destroyed,
|
130
|
+
timestamp: <timestamp in milliseconds>,
|
131
|
+
payload: {
|
132
|
+
object_id: <OBJECT_ID>
|
133
|
+
}
|
134
|
+
}
|
135
|
+
```
|
136
|
+
|
137
|
+
### Message frame for GC_START :
|
138
|
+
|
139
|
+
When the GC_START event is triggered, no payload is sent.
|
140
|
+
|
141
|
+
```yaml
|
142
|
+
{
|
143
|
+
event_type: gc_start,
|
144
|
+
timestamp: <timestamp in milliseconds>,
|
145
|
+
}
|
146
|
+
```
|
147
|
+
|
148
|
+
### Message frame for GC_END_SWEEP :
|
149
|
+
|
150
|
+
When the GC_END_SWEEP event is triggered, no payload is sent.
|
151
|
+
|
152
|
+
```yaml
|
153
|
+
{
|
154
|
+
event_type: gc_end_s,
|
155
|
+
timestamp: <timestamp in milliseconds>,
|
156
|
+
}
|
157
|
+
```
|
158
|
+
|
159
|
+
### Message frame for OBJECT_SPACE_DUMP :
|
160
|
+
|
161
|
+
```yaml
|
162
|
+
{
|
163
|
+
event_type: object_space_dump
|
164
|
+
timestamp: <timestamp in milliseconds>,
|
165
|
+
payload: [
|
166
|
+
{
|
167
|
+
object_id: <OBJECT_ID>,
|
168
|
+
snapshot_no: <SNAPSHOT_COUNT>,
|
169
|
+
class_name: <CLASS_NAME>,
|
170
|
+
references: [<OBJECT_ID>, <OBJECT_ID>, ... ],
|
171
|
+
file: <FILE_PATH>,
|
172
|
+
line: <LINE_NUMBER>,
|
173
|
+
size: <SIZE>
|
174
|
+
},
|
175
|
+
...
|
176
|
+
]
|
177
|
+
}
|
178
|
+
```
|
179
|
+
|
180
|
+
### Message from GC stats:
|
181
|
+
**Note: GC stat payload uses strings for keys**
|
182
|
+
|
183
|
+
```yaml
|
184
|
+
{
|
185
|
+
event_type: "gc_stats",
|
186
|
+
timestamp: <timestamp in milliseconds>,
|
187
|
+
payload: {
|
188
|
+
count:
|
189
|
+
heap_user:
|
190
|
+
heap_length:
|
191
|
+
heap_increment:
|
192
|
+
...
|
193
|
+
}
|
194
|
+
}
|
195
|
+
```
|