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
data/ext/rbkit_tracer.h
CHANGED
@@ -9,27 +9,19 @@
|
|
9
9
|
#include "msgpack.h"
|
10
10
|
|
11
11
|
// Structure is used to store profiling data
|
12
|
-
struct
|
12
|
+
typedef struct _rbkit_logger {
|
13
13
|
VALUE hooks[3];
|
14
14
|
VALUE enabled;
|
15
|
-
void (*funcs[3])(void *data, int event_index);
|
16
|
-
void *args[3];
|
17
15
|
void *data;
|
18
16
|
st_table *object_table;
|
19
17
|
st_table *str_table;
|
20
18
|
VALUE newobj_trace;
|
21
19
|
VALUE freeobj_trace;
|
22
|
-
int keep_remains;
|
23
20
|
msgpack_sbuffer *sbuf;
|
24
21
|
msgpack_packer *msgpacker;
|
25
|
-
};
|
22
|
+
} rbkit_logger;
|
26
23
|
|
27
24
|
char * tracer_string_recv(void *socket);
|
28
25
|
int tracer_string_send(void *socket, const char *message);
|
29
|
-
void pack_value_object(msgpack_packer *packer, VALUE value);
|
30
|
-
void pack_string(msgpack_packer *packer, char *string);
|
31
|
-
void pack_timestamp(msgpack_packer *packer);
|
32
|
-
void pack_event_header(msgpack_packer *packer, const char *event_type, int map_size);
|
33
|
-
void pack_pointer(msgpack_packer *packer, VALUE object_id);
|
34
26
|
|
35
27
|
#endif
|
data/lib/rbkit.rb
CHANGED
@@ -1,57 +1,64 @@
|
|
1
1
|
require "rbkit_tracer"
|
2
2
|
require "rbkit/timer"
|
3
|
+
require "rbkit/rbkit_gc"
|
3
4
|
require "objspace"
|
4
5
|
|
5
6
|
# Class implements user friendly interface in pure Ruby for profiler.
|
6
7
|
module Rbkit
|
8
|
+
DEFAULT_PUB_PORT = 5555
|
9
|
+
DEFAULT_REQ_PORT = 5556
|
10
|
+
|
7
11
|
class Profiler
|
8
12
|
attr_accessor :pub_port, :request_port
|
9
13
|
|
10
14
|
def initialize(pub_port, request_port)
|
15
|
+
[pub_port, request_port].each{|port| validate_port_range(port) }
|
11
16
|
@pub_port = pub_port
|
12
17
|
@request_port = request_port
|
13
18
|
@profiler_thread = nil
|
14
19
|
@stop_thread = false
|
15
20
|
@server_running = false
|
16
21
|
@gc_stats_timer = Rbkit::Timer.new(5) do
|
17
|
-
data =
|
18
|
-
|
19
|
-
max_objects_per_page = GC::INTERNAL_CONSTANTS[:HEAP_OBJ_LIMIT]
|
20
|
-
size_of_one_obj = GC::INTERNAL_CONSTANTS[:RVALUE_SIZE]
|
21
|
-
data[:total_heap_size] = no_of_allocated_pages * max_objects_per_page *
|
22
|
-
size_of_one_obj
|
23
|
-
data[:total_memsize] = ObjectSpace.memsize_of_all
|
24
|
-
Rbkit.send_hash_as_event(data, "gc_stats")
|
22
|
+
data = RbkitGC.stat
|
23
|
+
Rbkit.send_hash_as_event(data, Rbkit::EVENT_TYPES[:gc_stats])
|
25
24
|
end
|
26
25
|
@message_dispatch_timer = Rbkit::Timer.new(1) do
|
27
26
|
Rbkit.send_messages
|
28
27
|
end
|
29
28
|
end
|
30
29
|
|
31
|
-
def start_server(
|
32
|
-
|
30
|
+
def start_server(enable_object_trace: false, enable_gc_stats: false)
|
31
|
+
if @server_running || !Rbkit.start_stat_server(pub_port, request_port)
|
32
|
+
$stderr.puts "Rbkit server couldn't bind to socket, check if it is already" \
|
33
|
+
" running. Profiling data will not be available."
|
34
|
+
return false
|
35
|
+
end
|
36
|
+
Rbkit.start_stat_tracing if enable_object_trace
|
37
|
+
@enable_gc_stats = enable_gc_stats
|
38
|
+
@server_running = true
|
33
39
|
@profiler_thread = Thread.new do
|
34
|
-
Rbkit.start_stat_server(pub_port, request_port)
|
35
|
-
Rbkit.start_stat_tracing if enable_profiling
|
36
40
|
loop do
|
37
41
|
break if @stop_thread
|
38
42
|
incoming_request = Rbkit.poll_for_request
|
39
43
|
process_incoming_request(incoming_request)
|
40
|
-
@gc_stats_timer.run
|
44
|
+
@gc_stats_timer.run if @enable_gc_stats
|
41
45
|
@message_dispatch_timer.run
|
42
46
|
# Let us sleep this thread for a bit, so as other things can run.
|
43
47
|
sleep(0.05)
|
44
48
|
end
|
45
49
|
end
|
46
|
-
|
50
|
+
at_exit { make_clean_exit(exiting: true) }
|
51
|
+
true
|
47
52
|
end
|
48
53
|
|
49
54
|
def process_incoming_request(incoming_request)
|
50
55
|
case incoming_request
|
51
56
|
when "start_memory_profile"
|
52
57
|
Rbkit.start_stat_tracing
|
58
|
+
@enable_gc_stats = true
|
53
59
|
when "stop_memory_profile"
|
54
60
|
Rbkit.stop_stat_tracing
|
61
|
+
@enable_gc_stats = false
|
55
62
|
when "trigger_gc"
|
56
63
|
GC.start
|
57
64
|
when "objectspace_snapshot"
|
@@ -60,42 +67,57 @@ module Rbkit
|
|
60
67
|
end
|
61
68
|
|
62
69
|
def stop_server
|
63
|
-
return if !@server_running
|
64
70
|
Rbkit.stop_stat_server
|
65
|
-
@server_running = false
|
66
71
|
end
|
67
72
|
|
68
|
-
def make_clean_exit
|
73
|
+
def make_clean_exit(exiting: false)
|
74
|
+
return false if !@server_running
|
69
75
|
@stop_thread = true
|
70
76
|
stop_server
|
77
|
+
@server_running = false
|
78
|
+
true
|
71
79
|
end
|
72
|
-
end
|
73
80
|
|
74
|
-
|
81
|
+
private
|
75
82
|
|
76
|
-
|
77
|
-
|
78
|
-
@profiler = Rbkit::Profiler.new(pub_port, request_port)
|
79
|
-
@profiler.start_server(enable_profiling: true)
|
80
|
-
at_exit do
|
81
|
-
self.stop_server
|
83
|
+
def validate_port_range(port)
|
84
|
+
raise ArgumentError, 'Invalid port value' unless (1024..65000).include?(port)
|
82
85
|
end
|
83
86
|
end
|
84
87
|
|
85
|
-
|
86
|
-
|
87
|
-
#
|
88
|
-
# to the
|
89
|
-
|
90
|
-
|
88
|
+
########### Rbkit API ###########
|
89
|
+
|
90
|
+
# Starts the Rbkit server and waits for a client to connect and issue
|
91
|
+
# commands to the request_port, until then there's zero performance overhead.
|
92
|
+
# Profiling data is sent asynchronously over pub_port.
|
93
|
+
# This method can be called early in a ruby application so that
|
94
|
+
# whenever profiling needs to be done, the client can attach itself to the
|
95
|
+
# inactive server, do the profiling and leave.
|
96
|
+
def self.start_server(pub_port: DEFAULT_PUB_PORT, request_port: DEFAULT_REQ_PORT)
|
97
|
+
@profiler ||= Rbkit::Profiler.new(pub_port, request_port)
|
91
98
|
@profiler.start_server
|
92
|
-
|
93
|
-
|
94
|
-
|
99
|
+
end
|
100
|
+
|
101
|
+
# Starts the server with all tracepoints enabled by default. User can
|
102
|
+
# optionally disable tracepoints using the optional arguments.
|
103
|
+
# This method can be used to profile the startup process of a ruby
|
104
|
+
# application where sending commands from the client to enable
|
105
|
+
# profiling is not feasible.
|
106
|
+
def self.start_profiling(pub_port: DEFAULT_PUB_PORT, request_port: DEFAULT_REQ_PORT,
|
107
|
+
enable_object_trace: true, enable_gc_stats: true)
|
108
|
+
@profiler ||= Rbkit::Profiler.new(pub_port, request_port)
|
109
|
+
@profiler.start_server(enable_object_trace: enable_object_trace,
|
110
|
+
enable_gc_stats: enable_gc_stats)
|
95
111
|
end
|
96
112
|
|
97
113
|
# Stops profiling and brings down the rbkit server if it's running
|
98
114
|
def self.stop_server
|
99
|
-
@profiler.make_clean_exit
|
115
|
+
if !@profiler.nil? && @profiler.make_clean_exit
|
116
|
+
@profiler = nil
|
117
|
+
true
|
118
|
+
else
|
119
|
+
$stderr.puts "Cannot stop Rbkit server. Is it running?"
|
120
|
+
false
|
121
|
+
end
|
100
122
|
end
|
101
123
|
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require "objspace"
|
2
|
+
|
3
|
+
module Rbkit
|
4
|
+
class RbkitGC
|
5
|
+
# Returns a standardized hash containing the data
|
6
|
+
# returned by GC.stat
|
7
|
+
# @return [Hash] Keys :
|
8
|
+
# [count] Count of major and minor GCs so far
|
9
|
+
# [minor_gc_count] Count of minor GCs
|
10
|
+
# [major_gc_count] Count of major GCs
|
11
|
+
# [heap_allocated_pages] Count of allocated pages (heap_eden_pages + heap_tomb_pages)
|
12
|
+
# [heap_eden_pages] Count of pages which has atleast one live object
|
13
|
+
# [heap_tomb_pages] Count of pages which don't have any object yet
|
14
|
+
# [heap_allocatable_pages] Count of pages that will be allocated if Ruby runs out of heap
|
15
|
+
# [heap_sorted_length] Count of total number of sorted pages (>= heap_allocated_pages + heap_allocatable_pages)
|
16
|
+
# [heap_live_slots] Count of slots in all pages having live objects
|
17
|
+
# [heap_free_slots] Count of free slots in all pages
|
18
|
+
# [heap_final_slots] Count of zombie objects
|
19
|
+
# [heap_swept_slots] Count of slots swept after last GC
|
20
|
+
# [old_objects] Count of old generation objects
|
21
|
+
# [old_objects_limit] Old generation object count after which GC is triggered
|
22
|
+
# [total_allocated_objects] Number of created objects in the lifetime of the process
|
23
|
+
# [total_freed_objects] Number of freed objects in the lifetime of the process
|
24
|
+
# [malloc_increase_bytes] Malloc'ed bytes since last GC
|
25
|
+
# [malloc_increase_bytes_limit] Minor GC is triggered when malloc_increase_bytes exceeds this value
|
26
|
+
# [oldmalloc_increase_bytes] Malloc'ed bytes for old objects since last major GC
|
27
|
+
# [oldmalloc_increase_bytes_limit] Major GC is triggered with oldmalloc_increase_bytes exceeds this value
|
28
|
+
# [total_heap_size] heap_allocated_pages * max slots per page * size of one slot
|
29
|
+
# [total_memsize] ObjectSpace.memsize_of_all
|
30
|
+
def self.stat
|
31
|
+
stats = {}
|
32
|
+
data = GC.stat
|
33
|
+
|
34
|
+
stats[:count] = data[:count]
|
35
|
+
stats[:minor_gc_count] = data[:minor_gc_count]
|
36
|
+
stats[:major_gc_count] = data[:major_gc_count]
|
37
|
+
|
38
|
+
if RUBY_VERSION >= "2.2.0"
|
39
|
+
[
|
40
|
+
:heap_allocated_pages, :heap_eden_pages, :heap_tomb_pages,
|
41
|
+
:heap_allocatable_pages, :heap_sorted_length, :heap_live_slots,
|
42
|
+
:heap_free_slots, :heap_final_slots, :heap_swept_slots,
|
43
|
+
:old_objects, :old_objects_limit, :total_allocated_objects,
|
44
|
+
:total_freed_objects, :malloc_increase_bytes,
|
45
|
+
:malloc_increase_bytes_limit, :oldmalloc_increase_bytes,
|
46
|
+
:oldmalloc_increase_bytes_limit
|
47
|
+
].each do |key|
|
48
|
+
stats[key] = data[key]
|
49
|
+
end
|
50
|
+
elsif RUBY_VERSION >= "2.1.0"
|
51
|
+
stats[:heap_allocated_pages] = data[:heap_used]
|
52
|
+
stats[:heap_eden_pages] = data[:heap_eden_page_length]
|
53
|
+
stats[:heap_tomb_pages] = data[:heap_tomb_page_length]
|
54
|
+
stats[:heap_allocatable_pages] = data[:heap_increment]
|
55
|
+
stats[:heap_sorted_length] = data[:heap_length]
|
56
|
+
stats[:heap_live_slots] = data[:heap_live_slot]
|
57
|
+
stats[:heap_free_slots] = data[:heap_free_slot]
|
58
|
+
stats[:heap_final_slots] = data[:heap_final_slot]
|
59
|
+
stats[:heap_swept_slots] = data[:heap_swept_slot]
|
60
|
+
stats[:old_objects] = data[:old_object]
|
61
|
+
stats[:old_objects_limit] = data[:old_object_limit]
|
62
|
+
stats[:total_allocated_objects] = data[:total_allocated_object]
|
63
|
+
stats[:total_freed_objects] = data[:total_freed_object]
|
64
|
+
stats[:malloc_increase_bytes] = data[:malloc_increase]
|
65
|
+
stats[:malloc_increase_bytes_limit] = data[:malloc_limit]
|
66
|
+
stats[:oldmalloc_increase_bytes] = data[:oldmalloc_increase]
|
67
|
+
stats[:oldmalloc_increase_bytes_limit] = data[:oldmalloc_limit]
|
68
|
+
end
|
69
|
+
|
70
|
+
no_of_allocated_pages = stats[:heap_allocated_pages] rescue 0
|
71
|
+
max_objects_per_page = GC::INTERNAL_CONSTANTS[:HEAP_OBJ_LIMIT]
|
72
|
+
size_of_one_obj = GC::INTERNAL_CONSTANTS[:RVALUE_SIZE]
|
73
|
+
stats[:total_heap_size] = no_of_allocated_pages * max_objects_per_page *
|
74
|
+
size_of_one_obj
|
75
|
+
stats[:total_memsize] = ObjectSpace.memsize_of_all
|
76
|
+
stats
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
data/lib/rbkit/version.rb
CHANGED
data/logo.png
ADDED
Binary file
|
data/rbkit.gemspec
CHANGED
@@ -14,6 +14,7 @@ Gem::Specification.new do |s|
|
|
14
14
|
if s.respond_to? :required_rubygems_version=
|
15
15
|
s.required_rubygems_version = Gem::Requirement.new(">= 0")
|
16
16
|
end
|
17
|
+
s.required_ruby_version = '>= 2.1.0'
|
17
18
|
s.authors = ["Hemant Kumar", "Emil Soman", "Kashyap"]
|
18
19
|
s.description = %q{Something small for process management}
|
19
20
|
s.email = %q{hemant@codemancers.com emil@codemancers.com kashyap@codemancers.com}
|
data/setup.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'rbconfig'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
class Setup
|
5
|
+
attr_accessor :site_dir, :site_lib_dir, :site_arch_dir
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@site_dir = RbConfig::CONFIG["sitedir"]
|
9
|
+
@site_lib_dir = RbConfig::CONFIG["sitelibdir"]
|
10
|
+
@site_arch_dir = RbConfig::CONFIG["sitearchdir"]
|
11
|
+
end
|
12
|
+
|
13
|
+
def compile
|
14
|
+
Dir.chdir 'ext' do
|
15
|
+
if File.exist?("Makefile")
|
16
|
+
system("make clean")
|
17
|
+
end
|
18
|
+
|
19
|
+
system("#{Gem.ruby} extconf.rb")
|
20
|
+
system("make")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def copy_files
|
25
|
+
FileUtils.cp_r "lib/.", site_lib_dir, verbose: true
|
26
|
+
ext_path =
|
27
|
+
File.absolute_path "ext/rbkit_tracer.#{RbConfig::MAKEFILE_CONFIG['DLEXT']}"
|
28
|
+
FileUtils.cp_r ext_path, site_arch_dir, verbose: true
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
if __FILE__ == $0
|
33
|
+
Setup.new.tap do |setup|
|
34
|
+
setup.compile
|
35
|
+
setup.copy_files
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'gc_stat' do
|
4
|
+
let(:stat) { Rbkit::RbkitGC.stat }
|
5
|
+
it 'should have the correct gc stat keys' do
|
6
|
+
expect(stat.keys).to eql [
|
7
|
+
:count,
|
8
|
+
:minor_gc_count,
|
9
|
+
:major_gc_count,
|
10
|
+
:heap_allocated_pages,
|
11
|
+
:heap_eden_pages,
|
12
|
+
:heap_tomb_pages,
|
13
|
+
:heap_allocatable_pages,
|
14
|
+
:heap_sorted_length,
|
15
|
+
:heap_live_slots,
|
16
|
+
:heap_free_slots,
|
17
|
+
:heap_final_slots,
|
18
|
+
:heap_swept_slots,
|
19
|
+
:old_objects,
|
20
|
+
:old_objects_limit,
|
21
|
+
:total_allocated_objects,
|
22
|
+
:total_freed_objects,
|
23
|
+
:malloc_increase_bytes,
|
24
|
+
:malloc_increase_bytes_limit,
|
25
|
+
:oldmalloc_increase_bytes,
|
26
|
+
:oldmalloc_increase_bytes_limit,
|
27
|
+
:total_heap_size,
|
28
|
+
:total_memsize ]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'msgpack'
|
3
|
+
|
4
|
+
describe 'send_hash_as_event' do
|
5
|
+
let(:hash) { {'foo' => 'bar', 123 => "hello world"} }
|
6
|
+
let(:payload) { Rbkit::MESSAGE_FIELDS[:payload] }
|
7
|
+
let(:event_type) { Rbkit::MESSAGE_FIELDS[:event_type] }
|
8
|
+
describe 'when event_type is known' do
|
9
|
+
before do
|
10
|
+
Rbkit.start_profiling(enable_gc_stats: false, enable_object_trace: false)
|
11
|
+
Rbkit.send_hash_as_event(hash, Rbkit::EVENT_TYPES[:gc_stats])
|
12
|
+
packed_message = Rbkit.get_queued_messages
|
13
|
+
@message = MessagePack.unpack packed_message
|
14
|
+
Rbkit.stop_server
|
15
|
+
end
|
16
|
+
it 'should create a custom event with the serialized hash' do
|
17
|
+
expect(@message[payload].first[event_type]).to eql Rbkit::EVENT_TYPES[:gc_stats]
|
18
|
+
expect(@message[payload].first[payload]).to eql hash
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe 'when event_type is not known' do
|
23
|
+
it 'should raise NotImplementedError with a meaningful message' do
|
24
|
+
expect { Rbkit.send_hash_as_event(hash, 100) }
|
25
|
+
.to raise_error(NotImplementedError,
|
26
|
+
"Rbkit : Unpacking of event type '100' not implemented")
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'support/have_message_matcher'
|
3
|
+
require 'msgpack'
|
4
|
+
|
5
|
+
describe "obj_created event" do
|
6
|
+
let(:payload) { Rbkit::MESSAGE_FIELDS[:payload] }
|
7
|
+
let(:class_name) { Rbkit::MESSAGE_FIELDS[:class_name] }
|
8
|
+
let(:event_type) { Rbkit::MESSAGE_FIELDS[:event_type] }
|
9
|
+
let(:object_id) { Rbkit::MESSAGE_FIELDS[:object_id] }
|
10
|
+
let(:foo_info) do
|
11
|
+
@message_list[payload]
|
12
|
+
.select{|x| x[event_type] == Rbkit::EVENT_TYPES[:obj_created] &&
|
13
|
+
x[payload][class_name] =='Foo' }
|
14
|
+
end
|
15
|
+
let(:bar_info) do
|
16
|
+
@message_list[payload]
|
17
|
+
.select{|x| x[event_type] == Rbkit::EVENT_TYPES[:obj_created] &&
|
18
|
+
x[payload][class_name] =='Bar'}
|
19
|
+
end
|
20
|
+
let(:short_lived_bar_info) do
|
21
|
+
@message_list[payload]
|
22
|
+
.select{|x| x[event_type] == Rbkit::EVENT_TYPES[:obj_created] &&
|
23
|
+
x[payload][class_name] =='ShortLivedBar' }
|
24
|
+
end
|
25
|
+
before(:all) do
|
26
|
+
Rbkit.start_profiling(enable_gc_stats: false, enable_object_trace: true)
|
27
|
+
@foo_obj = Foo.new
|
28
|
+
packed_message = Rbkit.get_queued_messages
|
29
|
+
Rbkit.stop_server
|
30
|
+
@message_list = MessagePack.unpack packed_message
|
31
|
+
end
|
32
|
+
it "should be part of message list" do
|
33
|
+
expect(@message_list).to have_message(Rbkit::EVENT_TYPES[:obj_created])
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'should record objects only once' do
|
37
|
+
expect(foo_info.size).to eql 1
|
38
|
+
expect(bar_info.size).to eql 1
|
39
|
+
expect(short_lived_bar_info.size).to eql 1
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'should record correct object_id' do
|
43
|
+
expect(foo_info.first[payload][object_id]).to eql @foo_obj.object_id
|
44
|
+
expect(bar_info.first[payload][object_id]).to eql @foo_obj.bar.object_id
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'should record correct class_name' do
|
48
|
+
expect(foo_info.first[payload][class_name]).to eql @foo_obj.class.to_s
|
49
|
+
expect(bar_info.first[payload][class_name]).to eql @foo_obj.bar.class.to_s
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'support/have_message_matcher'
|
3
|
+
require 'msgpack'
|
4
|
+
|
5
|
+
describe "obj_destroyed event" do
|
6
|
+
let(:payload) { Rbkit::MESSAGE_FIELDS[:payload] }
|
7
|
+
let(:event_type) { Rbkit::MESSAGE_FIELDS[:event_type] }
|
8
|
+
let(:object_id) { Rbkit::MESSAGE_FIELDS[:object_id] }
|
9
|
+
let(:class_name) { Rbkit::MESSAGE_FIELDS[:class_name] }
|
10
|
+
let(:foo_info) do
|
11
|
+
@message_list[payload]
|
12
|
+
.select{|x| x[event_type] == Rbkit::EVENT_TYPES[:obj_destroyed] &&
|
13
|
+
x[payload][object_id] == @foo_obj.object_id }
|
14
|
+
end
|
15
|
+
let(:short_lived_bar_info) do
|
16
|
+
short_lived_bar_object_id = @message_list[payload]
|
17
|
+
.find{|x| x[event_type] == Rbkit::EVENT_TYPES[:obj_created] &&
|
18
|
+
x[payload][class_name] == 'ShortLivedBar'}[payload][object_id]
|
19
|
+
@message_list[payload]
|
20
|
+
.select{|x| x[event_type] == Rbkit::EVENT_TYPES[:obj_destroyed] &&
|
21
|
+
x[payload][object_id] == short_lived_bar_object_id}
|
22
|
+
end
|
23
|
+
before(:all) do
|
24
|
+
Rbkit.start_profiling(enable_gc_stats: false, enable_object_trace: true)
|
25
|
+
@foo_obj = Foo.new
|
26
|
+
GC.start
|
27
|
+
packed_message = Rbkit.get_queued_messages
|
28
|
+
Rbkit.stop_server
|
29
|
+
@message_list = MessagePack.unpack packed_message
|
30
|
+
end
|
31
|
+
it "should be part of message list" do
|
32
|
+
expect(@message_list).to have_message(Rbkit::EVENT_TYPES[:obj_destroyed])
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'should record the deleted object' do
|
36
|
+
expect(short_lived_bar_info.size).to eql 1
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'should not record the live object' do
|
40
|
+
expect(foo_info.size).to eql 0
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
|