stackprof 0.2.10 → 0.2.11

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.
@@ -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: