rbkit 0.0.1 → 0.1.6
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 +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
|
+
[](http://badge.fury.io/rb/rbkit)
|
5
|
+
[](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
|
+
```
|