stackprof 0.2.10 → 0.2.11

Sign up to get free protection for your applications and to get access to all the features.
@@ -5,9 +5,32 @@
5
5
  body {
6
6
  margin: 0;
7
7
  padding: 0;
8
- font-family: Monaco, "Liberation Mono", Courier, monospace;
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="flamegraph"></div>
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
- <div class="zoom"></div>
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])})
@@ -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
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'stackprof'
3
- s.version = '0.2.10'
3
+ s.version = '0.2.11'
4
4
  s.homepage = 'http://github.com/tmm1/stackprof'
5
5
 
6
6
  s.authors = 'Aman Gupta'
@@ -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.1, profile[:version]
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
- assert_equal nil, StackProf.results
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
- assert_equal nil, StackProf.results
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
- assert_equal nil, StackProf.results
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
- assert_equal "block in StackProfTest#test_object_allocation", frame[:name]
44
+ assert_includes frame[:name], "StackProfTest#test_object_allocation"
45
45
  assert_equal 2, frame[:samples]
46
- assert_equal profile_base_line, frame[:line]
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], :>, 1
65
+ assert_operator profile[:samples], :>=, 1
67
66
  frame = profile[:frames].values.first
68
- assert_equal "block in StackProfTest#math", frame[:name]
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], 5
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
- assert_equal "block (2 levels) in StackProfTest#test_custom", frame[:name]
94
- assert_equal profile_base_line+1, frame[:line]
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
- assert_equal 'block (2 levels) in StackProfTest#test_raw', profile[:frames][raw[-2]][:name]
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
- assert_empty profile[:frames]
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
- assert_equal 0, profile[:missed_samples]
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.10
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: 2016-09-29 00:00:00.000000000 Z
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.4.5.1
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: