stackprof 0.2.10 → 0.2.11
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +5 -5
- data/Gemfile.lock +4 -1
- data/README.md +1 -0
- data/bin/stackprof +3 -2
- data/ext/stackprof/stackprof.c +154 -19
- data/lib/stackprof/flamegraph/flamegraph.js +926 -300
- data/lib/stackprof/flamegraph/viewer.html +29 -23
- data/lib/stackprof/report.rb +41 -0
- data/sample.rb +3 -3
- data/stackprof.gemspec +1 -1
- data/test/test_stackprof.rb +20 -17
- metadata +3 -4
@@ -5,9 +5,32 @@
|
|
5
5
|
body {
|
6
6
|
margin: 0;
|
7
7
|
padding: 0;
|
8
|
-
font-family:
|
8
|
+
font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;
|
9
9
|
font-size: 10pt;
|
10
10
|
}
|
11
|
+
.overview-container {
|
12
|
+
position: relative;
|
13
|
+
}
|
14
|
+
.overview {
|
15
|
+
cursor: col-resize;
|
16
|
+
}
|
17
|
+
.overview-viewport-overlay {
|
18
|
+
position: absolute;
|
19
|
+
top: 0;
|
20
|
+
left: 0;
|
21
|
+
width: 1;
|
22
|
+
height: 1;
|
23
|
+
background-color: rgba(0, 0, 0, 0.25);
|
24
|
+
transform-origin: top left;
|
25
|
+
cursor: -moz-grab;
|
26
|
+
cursor: -webkit-grab;
|
27
|
+
cursor: grab;
|
28
|
+
}
|
29
|
+
.moving {
|
30
|
+
cursor: -moz-grabbing;
|
31
|
+
cursor: -webkit-grabbing;
|
32
|
+
cursor: grabbing;
|
33
|
+
}
|
11
34
|
.info {
|
12
35
|
display: block;
|
13
36
|
height: 40px;
|
@@ -36,32 +59,15 @@
|
|
36
59
|
max-width: 70%;
|
37
60
|
word-wrap: break-word;
|
38
61
|
}
|
39
|
-
.legend:hover + .flamegraph .flames:not(.highlighted) {
|
40
|
-
opacity: 0.25;
|
41
|
-
}
|
42
|
-
.legend:hover ~ .zoom .flames:not(.highlighted) {
|
43
|
-
opacity: 0.25;
|
44
|
-
}
|
45
|
-
.brush .extent {
|
46
|
-
stroke: #999;
|
47
|
-
fill-opacity: .125;
|
48
|
-
shape-rendering: crispEdges;
|
49
|
-
}
|
50
|
-
.label {
|
51
|
-
white-space: nowrap;
|
52
|
-
display: inline-flex;
|
53
|
-
align-items: center;
|
54
|
-
vertical-align: middle;
|
55
|
-
padding-left: 1px;
|
56
|
-
}
|
57
62
|
</style>
|
58
|
-
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
|
59
|
-
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.0.8/d3.min.js"></script>
|
60
63
|
<script src="flamegraph.js"></script>
|
61
64
|
</head>
|
62
65
|
<body>
|
63
66
|
<div class="legend"></div>
|
64
|
-
<div class="
|
67
|
+
<div class="overview-container">
|
68
|
+
<canvas class="overview"></canvas>
|
69
|
+
<div class="overview-viewport-overlay"></div>
|
70
|
+
</div>
|
65
71
|
<div class="info">
|
66
72
|
<div style="float: right; text-align: right">
|
67
73
|
<div class="samples"></div>
|
@@ -70,7 +76,7 @@
|
|
70
76
|
<div class="frame"></div>
|
71
77
|
<div class="file"></div>
|
72
78
|
</div>
|
73
|
-
<
|
79
|
+
<canvas class="flamegraph"></canvas>
|
74
80
|
<script type="text/javascript">
|
75
81
|
var queryDict = {}
|
76
82
|
location.search.substr(1).split("&").forEach(function(item) {queryDict[item.split("=")[0]] = decodeURIComponent(item.split("=")[1])})
|
data/lib/stackprof/report.rb
CHANGED
@@ -293,6 +293,47 @@ module StackProf
|
|
293
293
|
end
|
294
294
|
end
|
295
295
|
|
296
|
+
# Walk up and down the stack from a given starting point (name). Loops
|
297
|
+
# until `:exit` is selected
|
298
|
+
def walk_method(name)
|
299
|
+
method_choice = /#{Regexp.escape name}/
|
300
|
+
invalid_choice = false
|
301
|
+
|
302
|
+
# Continue walking up and down the stack until the users selects "exit"
|
303
|
+
while method_choice != :exit
|
304
|
+
print_method method_choice unless invalid_choice
|
305
|
+
STDOUT.puts "\n\n"
|
306
|
+
|
307
|
+
# Determine callers and callees for the current frame
|
308
|
+
new_frames = frames.select {|_, info| info[:name] =~ method_choice }
|
309
|
+
new_choices = new_frames.map {|frame, info| [
|
310
|
+
callers_for(frame).sort_by(&:last).reverse.map(&:first),
|
311
|
+
(info[:edges] || []).map{ |k, w| [data[:frames][k][:name], w] }.sort_by{ |k,v| -v }.map(&:first)
|
312
|
+
]}.flatten + [:exit]
|
313
|
+
|
314
|
+
# Print callers and callees for selection
|
315
|
+
STDOUT.puts "Select next method:"
|
316
|
+
new_choices.each_with_index do |method, index|
|
317
|
+
STDOUT.printf "%2d) %s\n", index + 1, method.to_s
|
318
|
+
end
|
319
|
+
|
320
|
+
# Pick selection
|
321
|
+
STDOUT.printf "> "
|
322
|
+
selection = STDIN.gets.chomp.to_i - 1
|
323
|
+
STDOUT.puts "\n\n\n"
|
324
|
+
|
325
|
+
# Determine if it was a valid choice
|
326
|
+
# (if not, don't re-run .print_method)
|
327
|
+
if new_choice = new_choices[selection]
|
328
|
+
invalid_choice = false
|
329
|
+
method_choice = new_choice == :exit ? :exit : %r/^#{Regexp.escape new_choice}$/
|
330
|
+
else
|
331
|
+
invalid_choice = true
|
332
|
+
STDOUT.puts "Invalid choice. Please select again..."
|
333
|
+
end
|
334
|
+
end
|
335
|
+
end
|
336
|
+
|
296
337
|
def print_files(sort_by_total=false, limit=nil, f = STDOUT)
|
297
338
|
list = files.map{ |file, vals| [file, vals.values.inject([0,0]){ |sum, n| add_lines(sum, n) }] }
|
298
339
|
list = list.sort_by{ |file, samples| -samples[1] }
|
data/sample.rb
CHANGED
@@ -24,9 +24,9 @@ class A
|
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
-
#profile = StackProf.run(:object, 1) do
|
28
|
-
#profile = StackProf.run(:wall, 1000) do
|
29
|
-
profile = StackProf.run(:cpu, 1000) do
|
27
|
+
#profile = StackProf.run(mode: :object, interval: 1) do
|
28
|
+
#profile = StackProf.run(mode: :wall, interval: 1000) do
|
29
|
+
profile = StackProf.run(mode: :cpu, interval: 1000) do
|
30
30
|
1_000_000.times do
|
31
31
|
A.new
|
32
32
|
end
|
data/stackprof.gemspec
CHANGED
data/test/test_stackprof.rb
CHANGED
@@ -6,7 +6,7 @@ require 'tempfile'
|
|
6
6
|
class StackProfTest < MiniTest::Test
|
7
7
|
def test_info
|
8
8
|
profile = StackProf.run{}
|
9
|
-
assert_equal 1.
|
9
|
+
assert_equal 1.2, profile[:version]
|
10
10
|
assert_equal :wall, profile[:mode]
|
11
11
|
assert_equal 1000, profile[:interval]
|
12
12
|
assert_equal 0, profile[:samples]
|
@@ -18,16 +18,16 @@ class StackProfTest < MiniTest::Test
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def test_start_stop_results
|
21
|
-
|
21
|
+
assert_nil StackProf.results
|
22
22
|
assert_equal true, StackProf.start
|
23
23
|
assert_equal false, StackProf.start
|
24
24
|
assert_equal true, StackProf.running?
|
25
|
-
|
25
|
+
assert_nil StackProf.results
|
26
26
|
assert_equal true, StackProf.stop
|
27
27
|
assert_equal false, StackProf.stop
|
28
28
|
assert_equal false, StackProf.running?
|
29
29
|
assert_kind_of Hash, StackProf.results
|
30
|
-
|
30
|
+
assert_nil StackProf.results
|
31
31
|
end
|
32
32
|
|
33
33
|
def test_object_allocation
|
@@ -41,13 +41,12 @@ class StackProfTest < MiniTest::Test
|
|
41
41
|
assert_equal 2, profile[:samples]
|
42
42
|
|
43
43
|
frame = profile[:frames].values.first
|
44
|
-
|
44
|
+
assert_includes frame[:name], "StackProfTest#test_object_allocation"
|
45
45
|
assert_equal 2, frame[:samples]
|
46
|
-
|
46
|
+
assert_includes [profile_base_line - 2, profile_base_line], frame[:line]
|
47
47
|
assert_equal [1, 1], frame[:lines][profile_base_line+1]
|
48
48
|
assert_equal [1, 1], frame[:lines][profile_base_line+2]
|
49
|
-
|
50
|
-
frame = profile[:frames].values[1]
|
49
|
+
frame = profile[:frames].values[1] if RUBY_VERSION < '2.3'
|
51
50
|
assert_equal [2, 0], frame[:lines][profile_base_line]
|
52
51
|
end
|
53
52
|
|
@@ -63,9 +62,9 @@ class StackProfTest < MiniTest::Test
|
|
63
62
|
math
|
64
63
|
end
|
65
64
|
|
66
|
-
assert_operator profile[:samples],
|
65
|
+
assert_operator profile[:samples], :>=, 1
|
67
66
|
frame = profile[:frames].values.first
|
68
|
-
|
67
|
+
assert_includes frame[:name], "StackProfTest#math"
|
69
68
|
end
|
70
69
|
|
71
70
|
def test_walltime
|
@@ -75,7 +74,7 @@ class StackProfTest < MiniTest::Test
|
|
75
74
|
|
76
75
|
frame = profile[:frames].values.first
|
77
76
|
assert_equal "StackProfTest#idle", frame[:name]
|
78
|
-
assert_in_delta 200, frame[:samples],
|
77
|
+
assert_in_delta 200, frame[:samples], 25
|
79
78
|
end
|
80
79
|
|
81
80
|
def test_custom
|
@@ -90,8 +89,8 @@ class StackProfTest < MiniTest::Test
|
|
90
89
|
assert_equal 10, profile[:samples]
|
91
90
|
|
92
91
|
frame = profile[:frames].values.first
|
93
|
-
|
94
|
-
|
92
|
+
assert_includes frame[:name], "StackProfTest#test_custom"
|
93
|
+
assert_includes [profile_base_line-2, profile_base_line+1], frame[:line]
|
95
94
|
assert_equal [10, 10], frame[:lines][profile_base_line+2]
|
96
95
|
end
|
97
96
|
|
@@ -105,7 +104,8 @@ class StackProfTest < MiniTest::Test
|
|
105
104
|
raw = profile[:raw]
|
106
105
|
assert_equal 10, raw[-1]
|
107
106
|
assert_equal raw[0] + 2, raw.size
|
108
|
-
|
107
|
+
assert_includes profile[:frames][raw[-2]][:name], 'StackProfTest#test_raw'
|
108
|
+
assert_equal 10, profile[:raw_timestamp_deltas].size
|
109
109
|
end
|
110
110
|
|
111
111
|
def test_fork
|
@@ -120,15 +120,18 @@ class StackProfTest < MiniTest::Test
|
|
120
120
|
end
|
121
121
|
|
122
122
|
def test_gc
|
123
|
-
profile = StackProf.run(interval: 100) do
|
123
|
+
profile = StackProf.run(interval: 100, raw: true) do
|
124
124
|
5.times do
|
125
125
|
GC.start
|
126
126
|
end
|
127
127
|
end
|
128
128
|
|
129
|
-
|
129
|
+
raw = profile[:raw]
|
130
|
+
gc_frame = profile[:frames].values.find{ |f| f[:name] == "(garbage collection)" }
|
131
|
+
assert gc_frame
|
132
|
+
assert_equal gc_frame[:samples], profile[:gc_samples]
|
130
133
|
assert_operator profile[:gc_samples], :>, 0
|
131
|
-
|
134
|
+
assert_operator profile[:missed_samples], :<=, 10
|
132
135
|
end
|
133
136
|
|
134
137
|
def test_out
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: stackprof
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.11
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aman Gupta
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-11-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake-compiler
|
@@ -109,9 +109,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
109
109
|
version: '0'
|
110
110
|
requirements: []
|
111
111
|
rubyforge_project:
|
112
|
-
rubygems_version: 2.
|
112
|
+
rubygems_version: 2.6.13
|
113
113
|
signing_key:
|
114
114
|
specification_version: 4
|
115
115
|
summary: sampling callstack-profiler for ruby 2.1+
|
116
116
|
test_files: []
|
117
|
-
has_rdoc:
|