memprof 0.2.9 → 0.3.0
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.
- data/.gitignore +4 -0
- data/Rakefile +30 -0
- data/bin/memprof +158 -0
- data/ext/bin_api.h +6 -2
- data/ext/elf.c +146 -46
- data/ext/extconf.rb +39 -13
- data/ext/mach.c +3 -3
- data/ext/memprof.c +923 -95
- data/ext/tramp.c +2 -2
- data/ext/util.c +1 -0
- data/ext/util.h +34 -2
- data/lib/memprof/signal.rb +16 -0
- data/memprof.gemspec +5 -1
- data/spec/memprof_spec.rb +2 -2
- data/spec/memprof_uploader_spec.rb +117 -0
- metadata +35 -8
- data/lib/memprof/usr2.rb +0 -10
data/ext/tramp.c
CHANGED
@@ -123,7 +123,7 @@ hook_freelist(int entry, void *tramp)
|
|
123
123
|
void
|
124
124
|
insert_tramp(const char *trampee, void *tramp)
|
125
125
|
{
|
126
|
-
void *trampee_addr = bin_find_symbol(trampee, NULL);
|
126
|
+
void *trampee_addr = bin_find_symbol(trampee, NULL, 0);
|
127
127
|
int inline_ent = inline_tramp_size;
|
128
128
|
|
129
129
|
if (trampee_addr == NULL) {
|
@@ -136,7 +136,7 @@ insert_tramp(const char *trampee, void *tramp)
|
|
136
136
|
}
|
137
137
|
} else {
|
138
138
|
tramp_table[tramp_size].addr = tramp;
|
139
|
-
if (bin_update_image(trampee, &tramp_table[tramp_size]) != 0)
|
139
|
+
if (bin_update_image(trampee, &tramp_table[tramp_size], NULL) != 0)
|
140
140
|
errx(EX_SOFTWARE, "Failed to insert tramp for %s", trampee);
|
141
141
|
tramp_size++;
|
142
142
|
}
|
data/ext/util.c
CHANGED
data/ext/util.h
CHANGED
@@ -13,20 +13,52 @@
|
|
13
13
|
struct memprof_config {
|
14
14
|
void *gc_sweep;
|
15
15
|
size_t gc_sweep_size;
|
16
|
+
|
16
17
|
void *finalize_list;
|
17
18
|
size_t finalize_list_size;
|
19
|
+
|
18
20
|
void *rb_gc_force_recycle;
|
19
21
|
size_t rb_gc_force_recycle_size;
|
22
|
+
|
20
23
|
void *freelist;
|
21
24
|
void *classname;
|
22
25
|
void *add_freelist;
|
26
|
+
void *timeofday;
|
27
|
+
|
23
28
|
void *rb_mark_table_add_filename;
|
29
|
+
|
30
|
+
void *bm_mark;
|
31
|
+
void *blk_free;
|
32
|
+
void *thread_mark;
|
33
|
+
|
24
34
|
void *heaps;
|
25
35
|
void *heaps_used;
|
36
|
+
|
26
37
|
size_t sizeof_RVALUE;
|
27
38
|
size_t sizeof_heaps_slot;
|
28
|
-
|
29
|
-
|
39
|
+
|
40
|
+
size_t offset_heaps_slot_limit;
|
41
|
+
size_t offset_heaps_slot_slot;
|
42
|
+
|
43
|
+
size_t offset_BLOCK_body;
|
44
|
+
size_t offset_BLOCK_var;
|
45
|
+
size_t offset_BLOCK_cref;
|
46
|
+
size_t offset_BLOCK_prev;
|
47
|
+
size_t offset_BLOCK_self;
|
48
|
+
size_t offset_BLOCK_klass;
|
49
|
+
size_t offset_BLOCK_wrapper;
|
50
|
+
size_t offset_BLOCK_orig_thread;
|
51
|
+
size_t offset_BLOCK_block_obj;
|
52
|
+
size_t offset_BLOCK_scope;
|
53
|
+
size_t offset_BLOCK_dyna_vars;
|
54
|
+
|
55
|
+
size_t offset_METHOD_klass;
|
56
|
+
size_t offset_METHOD_rklass;
|
57
|
+
size_t offset_METHOD_recv;
|
58
|
+
size_t offset_METHOD_id;
|
59
|
+
size_t offset_METHOD_oid;
|
60
|
+
size_t offset_METHOD_body;
|
61
|
+
|
30
62
|
size_t pagesize;
|
31
63
|
};
|
32
64
|
|
@@ -0,0 +1,16 @@
|
|
1
|
+
begin
|
2
|
+
require File.expand_path('../../memprof', __FILE__)
|
3
|
+
rescue LoadError
|
4
|
+
require File.expand_path('../../../ext/memprof', __FILE__)
|
5
|
+
end
|
6
|
+
|
7
|
+
Memprof.start
|
8
|
+
old_handler = trap('URG'){
|
9
|
+
pid = Process.pid
|
10
|
+
fork{
|
11
|
+
GC.start
|
12
|
+
Memprof.dump_all("/tmp/memprof-#{pid}-#{Time.now.to_i}.json")
|
13
|
+
exit!
|
14
|
+
}
|
15
|
+
old_handler.call if old_handler
|
16
|
+
}
|
data/memprof.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
spec = Gem::Specification.new do |s|
|
2
2
|
s.name = 'memprof'
|
3
|
-
s.version = '0.
|
3
|
+
s.version = '0.3.0'
|
4
4
|
s.date = '2010-03-15'
|
5
5
|
s.summary = 'Ruby Memory Profiler'
|
6
6
|
s.description = "Ruby memory profiler similar to bleak_house, but without patches to the Ruby VM"
|
@@ -9,5 +9,9 @@ spec = Gem::Specification.new do |s|
|
|
9
9
|
s.authors = ["Joe Damato", "Aman Gupta", "Jake Douglas", "Rob Benson"]
|
10
10
|
s.email = ["joe@memprof.com", "aman@memprof.com", "jake@memprof.com"]
|
11
11
|
s.extensions = "ext/extconf.rb"
|
12
|
+
s.bindir = 'bin'
|
13
|
+
s.executables << 'memprof'
|
12
14
|
s.files = `git ls-files`.split
|
15
|
+
s.add_dependency('rest-client', '>= 1.4.2')
|
16
|
+
s.add_dependency('term-ansicolor')
|
13
17
|
end
|
data/spec/memprof_spec.rb
CHANGED
@@ -76,7 +76,7 @@ describe Memprof do
|
|
76
76
|
Memprof.stop
|
77
77
|
Memprof.dump_all(filename)
|
78
78
|
|
79
|
-
obj = File.open(filename, 'r').
|
79
|
+
obj = File.open(filename, 'r').readlines.find do |line|
|
80
80
|
line =~ /"dump out the entire heap"/
|
81
81
|
end
|
82
82
|
|
@@ -90,7 +90,7 @@ describe Memprof do
|
|
90
90
|
@str = "some random" + " string"
|
91
91
|
Memprof.dump_all(filename)
|
92
92
|
|
93
|
-
obj = File.open(filename, 'r').
|
93
|
+
obj = File.open(filename, 'r').readlines.find do |line|
|
94
94
|
line =~ /"some random string"/
|
95
95
|
end
|
96
96
|
|
@@ -0,0 +1,117 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bacon'
|
3
|
+
Bacon.summary_on_exit
|
4
|
+
|
5
|
+
describe "MemprofUploader" do
|
6
|
+
|
7
|
+
it "should display help output with -h" do
|
8
|
+
output = `ruby bin/memprof -h`
|
9
|
+
output.should =~ /Memprof Uploader/
|
10
|
+
output.should =~ /Usage:/
|
11
|
+
$?.exitstatus.should == 0
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should fail without a pid being passed" do
|
15
|
+
output = `ruby bin/memprof -n SomeLabel -k abcdef`
|
16
|
+
output.should =~ /Missing PID!/
|
17
|
+
$?.exitstatus.should == 1
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should fail without a name being passed" do
|
21
|
+
output = `ruby bin/memprof -p 123 -k abcdef`
|
22
|
+
output.should =~ /Missing name!/
|
23
|
+
$?.exitstatus.should == 1
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should fail without an API key" do
|
27
|
+
output = `ruby bin/memprof -p 123 -n SomeLabel`
|
28
|
+
output.should =~ /Missing API key!/
|
29
|
+
$?.exitstatus.should == 1
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should fail with an invalid pid" do
|
33
|
+
output = `ruby bin/memprof -p 99999999 -n Label -k abcdef`
|
34
|
+
output.should =~ Regexp.new("No such process 99999999!")
|
35
|
+
$?.exitstatus.should == 1
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should fail when the target process does not create a new file within 5 sec" do
|
39
|
+
pid = fork { sleep 5; exit! }
|
40
|
+
Process.detach(pid)
|
41
|
+
output = `ruby bin/memprof -p #{pid} -n Label -k abcdef`
|
42
|
+
output.should =~ Regexp.new("Waiting 5 seconds for process #{pid} to create a new dump...")
|
43
|
+
output.should =~ Regexp.new("Timed out after waiting 5 seconds")
|
44
|
+
$?.exitstatus.should == 1
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should WORK and wait for a dump to complete if it's IN_PROGRESS" do
|
48
|
+
pid = fork {
|
49
|
+
# create a fake file
|
50
|
+
filename = "/tmp/memprof-#{Process.pid}-#{Time.now.to_i}.json.IN_PROGRESS"
|
51
|
+
# simulate dump in progress
|
52
|
+
trap("URG") { File.open(filename, "w") {|f| f.write("foo") }; sleep 1 }
|
53
|
+
# should get signaled somewhere in here and execute the handler before exiting.
|
54
|
+
sleep 5
|
55
|
+
# rename the file to simulate completion of the dump writeout.
|
56
|
+
File.rename(filename, filename.sub(/\.IN_PROGRESS/, ""))
|
57
|
+
exit!
|
58
|
+
}
|
59
|
+
Process.detach(pid)
|
60
|
+
output = `ruby bin/memprof -p #{pid} -n Label -k abcdef -t`
|
61
|
+
output.should =~ Regexp.new("Waiting 5 seconds for process #{pid} to create a new dump...")
|
62
|
+
output.should =~ Regexp.new("Found file /tmp/memprof-#{pid}-\\d*.json\\.?\\w*")
|
63
|
+
output.should =~ Regexp.new("Dump in progress. Waiting 60 seconds for it to complete...")
|
64
|
+
output.should =~ Regexp.new("Finished!")
|
65
|
+
file = output.slice(Regexp.new("/tmp/memprof-#{pid}-\\d*.json\\.?\\w*"))
|
66
|
+
# make sure both files are gone
|
67
|
+
File.exist?(file).should == false
|
68
|
+
File.exist?(file.sub(/\.IN_PROGRESS/, "") + ".gz").should == false
|
69
|
+
$?.exitstatus.should == 0
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should WORK and delete the dump file after it's done, by default" do
|
73
|
+
pid = fork {
|
74
|
+
require File.dirname(__FILE__) + "/../lib/memprof/signal"
|
75
|
+
# should get signaled somewhere in here and execute the handler before exiting.
|
76
|
+
sleep 5
|
77
|
+
exit!
|
78
|
+
}
|
79
|
+
Process.detach(pid)
|
80
|
+
sleep 2
|
81
|
+
output = `ruby bin/memprof -p #{pid} -n TestDump -k abcdef -t`
|
82
|
+
output.should =~ Regexp.new("Waiting 5 seconds for process #{pid} to create a new dump...")
|
83
|
+
output.should =~ Regexp.new("Found file /tmp/memprof-#{pid}-\\d*.json\\.?\\w*")
|
84
|
+
output.should =~ Regexp.new("Finished!")
|
85
|
+
file = output.slice(Regexp.new("/tmp/memprof-#{pid}-\\d*.json\\.?\\w*"))
|
86
|
+
# make sure both files are gone
|
87
|
+
File.exist?(file).should == false
|
88
|
+
File.exist?(file.sub(/\.IN_PROGRESS/, "") + ".gz").should == false
|
89
|
+
$?.exitstatus.should == 0
|
90
|
+
end
|
91
|
+
|
92
|
+
it "should WORK and leave the dump file after it's done, with --no-delete" do
|
93
|
+
pid = fork {
|
94
|
+
require File.dirname(__FILE__) + "/../lib/memprof/signal"
|
95
|
+
# should get signaled somewhere in here and execute the handler before exiting.
|
96
|
+
sleep 5
|
97
|
+
exit!
|
98
|
+
}
|
99
|
+
Process.detach(pid)
|
100
|
+
sleep 2
|
101
|
+
output = `ruby bin/memprof -p #{pid} -n TestDump -k abcdef -t --no-delete`
|
102
|
+
output.should =~ Regexp.new("Waiting 5 seconds for process #{pid} to create a new dump...")
|
103
|
+
output.should =~ Regexp.new("Found file /tmp/memprof-#{pid}-\\d*.json\\w*")
|
104
|
+
output.should =~ Regexp.new("Finished!")
|
105
|
+
file = output.slice(Regexp.new("/tmp/memprof-#{pid}-\\d*.json\\.?\\w*"))
|
106
|
+
# Make sure it deleted the temporary one
|
107
|
+
if file =~ /\.IN_PROGRESS/
|
108
|
+
File.exist?(file).should == false
|
109
|
+
end
|
110
|
+
# make sure it left the completed one
|
111
|
+
file = file.sub(/\.IN_PROGRESS/, "") + ".gz"
|
112
|
+
File.exist?(file).should == true
|
113
|
+
File.delete(file)
|
114
|
+
$?.exitstatus.should == 0
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
-
-
|
8
|
-
-
|
9
|
-
version: 0.
|
7
|
+
- 3
|
8
|
+
- 0
|
9
|
+
version: 0.3.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Joe Damato
|
@@ -19,15 +19,40 @@ cert_chain: []
|
|
19
19
|
|
20
20
|
date: 2010-03-15 00:00:00 -07:00
|
21
21
|
default_executable:
|
22
|
-
dependencies:
|
23
|
-
|
22
|
+
dependencies:
|
23
|
+
- !ruby/object:Gem::Dependency
|
24
|
+
name: rest-client
|
25
|
+
prerelease: false
|
26
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
27
|
+
requirements:
|
28
|
+
- - ">="
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
segments:
|
31
|
+
- 1
|
32
|
+
- 4
|
33
|
+
- 2
|
34
|
+
version: 1.4.2
|
35
|
+
type: :runtime
|
36
|
+
version_requirements: *id001
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: term-ansicolor
|
39
|
+
prerelease: false
|
40
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
41
|
+
requirements:
|
42
|
+
- - ">="
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
segments:
|
45
|
+
- 0
|
46
|
+
version: "0"
|
47
|
+
type: :runtime
|
48
|
+
version_requirements: *id002
|
24
49
|
description: Ruby memory profiler similar to bleak_house, but without patches to the Ruby VM
|
25
50
|
email:
|
26
51
|
- joe@memprof.com
|
27
52
|
- aman@memprof.com
|
28
53
|
- jake@memprof.com
|
29
|
-
executables:
|
30
|
-
|
54
|
+
executables:
|
55
|
+
- memprof
|
31
56
|
extensions:
|
32
57
|
- ext/extconf.rb
|
33
58
|
extra_rdoc_files: []
|
@@ -36,6 +61,7 @@ files:
|
|
36
61
|
- .gitignore
|
37
62
|
- README
|
38
63
|
- Rakefile
|
64
|
+
- bin/memprof
|
39
65
|
- ext/arch.h
|
40
66
|
- ext/bin_api.h
|
41
67
|
- ext/elf.c
|
@@ -55,9 +81,10 @@ files:
|
|
55
81
|
- ext/x86_64.h
|
56
82
|
- ext/x86_gen.h
|
57
83
|
- lib/memprof/middleware.rb
|
58
|
-
- lib/memprof/
|
84
|
+
- lib/memprof/signal.rb
|
59
85
|
- memprof.gemspec
|
60
86
|
- spec/memprof_spec.rb
|
87
|
+
- spec/memprof_uploader_spec.rb
|
61
88
|
has_rdoc: true
|
62
89
|
homepage: http://github.com/ice799/memprof
|
63
90
|
licenses: []
|