stackprof 0.2.16 → 0.2.17
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +43 -0
- data/README.md +54 -55
- data/Rakefile +11 -25
- data/ext/stackprof/stackprof.c +20 -8
- data/lib/stackprof.rb +1 -1
- data/lib/stackprof/report.rb +1 -1
- data/stackprof.gemspec +1 -1
- data/test/test_stackprof.rb +36 -9
- metadata +7 -8
- data/.travis.yml +0 -21
- data/Dockerfile +0 -21
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b55691b8d1966ba4b2b2458a4908b2a2d5b65f2074dfe3b3b1b6350f752704ec
|
4
|
+
data.tar.gz: 79e2a0508a1c722f39cc61d39b0577cfb5520669a7a2db4cadac6c49dcb1267a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2fa22779f03c332a3680f526bf1df29553588773fabeb00da327af3525018e535e973bafd990254c6ad50516faf5e8b1d087bb7c208c99d0b512d99ccdef53bb
|
7
|
+
data.tar.gz: 73ba1328c793b0c0c4657e7826f4bf2cd52102c61a2ca2e3e0b1c5240ffe96ee0ec328ea831b1592c10b4e13c6aec2bb9d28fd05e93ddef999d5131e55124362
|
@@ -0,0 +1,43 @@
|
|
1
|
+
name: CI
|
2
|
+
|
3
|
+
on: [push, pull_request]
|
4
|
+
|
5
|
+
jobs:
|
6
|
+
rubies:
|
7
|
+
runs-on: ubuntu-latest
|
8
|
+
strategy:
|
9
|
+
fail-fast: false
|
10
|
+
matrix:
|
11
|
+
ruby: [ ruby-head, '3.0', '2.7', '2.6', '2.5', '2.4', '2.3', '2.2' ]
|
12
|
+
steps:
|
13
|
+
- name: Checkout
|
14
|
+
uses: actions/checkout@v2
|
15
|
+
- name: Set up Ruby
|
16
|
+
uses: ruby/setup-ruby@v1
|
17
|
+
with:
|
18
|
+
ruby-version: ${{ matrix.ruby }}
|
19
|
+
- name: Install dependencies
|
20
|
+
run: bundle install
|
21
|
+
- name: Run test
|
22
|
+
run: rake
|
23
|
+
- name: Install gem
|
24
|
+
run: rake install
|
25
|
+
platforms:
|
26
|
+
strategy:
|
27
|
+
matrix:
|
28
|
+
os: [macos]
|
29
|
+
ruby: ['3.0']
|
30
|
+
runs-on: ${{ matrix.os }}-latest
|
31
|
+
steps:
|
32
|
+
- name: Checkout
|
33
|
+
uses: actions/checkout@v2
|
34
|
+
- name: Set up Ruby
|
35
|
+
uses: ruby/setup-ruby@v1
|
36
|
+
with:
|
37
|
+
ruby-version: ${{ matrix.ruby }}
|
38
|
+
- name: Install dependencies
|
39
|
+
run: bundle install
|
40
|
+
- name: Run test
|
41
|
+
run: rake
|
42
|
+
- name: Install gem
|
43
|
+
run: rake install
|
data/README.md
CHANGED
@@ -81,21 +81,21 @@ $ stackprof tmp/stackprof-cpu-*.dump --method 'Object#present?'
|
|
81
81
|
|
82
82
|
For an experimental version of WebUI reporting of stackprof, see [stackprof-webnav](https://github.com/alisnic/stackprof-webnav)
|
83
83
|
|
84
|
-
|
84
|
+
To generate flamegraphs with Stackprof, additional data must be collected using the `raw: true` flag. Once you've collected results with this flag enabled, generate a flamegraph with:
|
85
85
|
|
86
86
|
```
|
87
87
|
$ stackprof --flamegraph tmp/stackprof-cpu-myapp.dump > tmp/flamegraph
|
88
88
|
```
|
89
89
|
|
90
|
-
|
90
|
+
After the flamegraph has been generated, you can generate a viewer command with:
|
91
91
|
|
92
92
|
```
|
93
93
|
$ stackprof --flamegraph-viewer=tmp/flamegraph
|
94
94
|
```
|
95
95
|
|
96
|
-
The `--flamegraph-viewer` command will output the exact shell command you need to run to open the `tmp/flamegraph` you generated with the built
|
96
|
+
The `--flamegraph-viewer` command will output the exact shell command you need to run in order to open the `tmp/flamegraph` you generated with the built-in stackprof flamegraph viewer:
|
97
97
|
|
98
|
-
![](http://i.imgur.com/EwndrgD.png)
|
98
|
+
![Flamegraph Viewer](http://i.imgur.com/EwndrgD.png)
|
99
99
|
|
100
100
|
Alternatively, you can generate a flamegraph that uses [d3-flame-graph](https://github.com/spiermar/d3-flame-graph):
|
101
101
|
|
@@ -107,16 +107,16 @@ And just open the result by your browser.
|
|
107
107
|
|
108
108
|
## Sampling
|
109
109
|
|
110
|
-
|
110
|
+
Four sampling modes are supported:
|
111
111
|
|
112
|
-
-
|
113
|
-
-
|
114
|
-
-
|
115
|
-
-
|
112
|
+
- `:wall` (using `ITIMER_REAL` and `SIGALRM`) [default mode]
|
113
|
+
- `:cpu` (using `ITIMER_PROF` and `SIGPROF`)
|
114
|
+
- `:object` (using `RUBY_INTERNAL_EVENT_NEWOBJ`)
|
115
|
+
- `:custom` (user-defined via `StackProf.sample`)
|
116
116
|
|
117
|
-
|
117
|
+
Samplers have a tuneable interval which can be used to reduce overhead or increase granularity:
|
118
118
|
|
119
|
-
-
|
119
|
+
- Wall time: sample every _interval_ microseconds of wallclock time (default: 1000)
|
120
120
|
|
121
121
|
```ruby
|
122
122
|
StackProf.run(mode: :wall, out: 'tmp/stackprof.dump', interval: 1000) do
|
@@ -124,7 +124,7 @@ StackProf.run(mode: :wall, out: 'tmp/stackprof.dump', interval: 1000) do
|
|
124
124
|
end
|
125
125
|
```
|
126
126
|
|
127
|
-
-
|
127
|
+
- CPU time: sample every _interval_ microseconds of CPU activity (default: 1000 = 1 millisecond)
|
128
128
|
|
129
129
|
```ruby
|
130
130
|
StackProf.run(mode: :cpu, out: 'tmp/stackprof.dump', interval: 1000) do
|
@@ -132,7 +132,7 @@ StackProf.run(mode: :cpu, out: 'tmp/stackprof.dump', interval: 1000) do
|
|
132
132
|
end
|
133
133
|
```
|
134
134
|
|
135
|
-
-
|
135
|
+
- Object allocation: sample every _interval_ allocations (default: 1)
|
136
136
|
|
137
137
|
|
138
138
|
```ruby
|
@@ -141,36 +141,36 @@ StackProf.run(mode: :object, out: 'tmp/stackprof.dump', interval: 1) do
|
|
141
141
|
end
|
142
142
|
```
|
143
143
|
|
144
|
-
|
145
|
-
including both mark and sweep phases.
|
146
|
-
that are hard to follow
|
147
|
-
|
144
|
+
By default, samples taken during garbage collection will show as garbage collection frames
|
145
|
+
including both mark and sweep phases. For longer traces, these can leave gaps in a flamegraph
|
146
|
+
that are hard to follow. They can be disabled by setting the `ignore_gc` option to true.
|
147
|
+
Garbage collection time will still be present in the profile but not explicitly marked with
|
148
148
|
its own frame.
|
149
149
|
|
150
|
-
|
150
|
+
Samples are taken using a combination of three new C-APIs in ruby 2.1:
|
151
151
|
|
152
|
-
-
|
152
|
+
- Signal handlers enqueue a sampling job using `rb_postponed_job_register_one`.
|
153
153
|
this ensures callstack samples can be taken safely, in case the VM is garbage collecting
|
154
154
|
or in some other inconsistent state during the interruption.
|
155
155
|
|
156
|
-
-
|
157
|
-
to the VM's call stack.
|
156
|
+
- Stack frames are collected via `rb_profile_frames`, which provides low-overhead C-API access
|
157
|
+
to the VM's call stack. No object allocations occur in this path, allowing stackprof to collect
|
158
158
|
callstacks in allocation mode.
|
159
159
|
|
160
|
-
-
|
160
|
+
- In allocation mode, samples are taken via `rb_tracepoint_new(RUBY_INTERNAL_EVENT_NEWOBJ)`,
|
161
161
|
which provides a notification every time the VM allocates a new object.
|
162
162
|
|
163
163
|
## Aggregation
|
164
164
|
|
165
|
-
|
166
|
-
|
165
|
+
Each sample consists of N stack frames, where a frame looks something like `MyClass#method` or `block in MySingleton.method`.
|
166
|
+
For each of these frames in the sample, the profiler collects a few pieces of metadata:
|
167
167
|
|
168
|
-
- samples
|
169
|
-
- total_samples
|
170
|
-
- lines
|
171
|
-
- edges
|
168
|
+
- `samples`: Number of samples where this was the topmost frame
|
169
|
+
- `total_samples`: Samples where this frame was in the stack
|
170
|
+
- `lines`: Samples per line number in this frame
|
171
|
+
- `edges`: Samples per callee frame (methods invoked by this frame)
|
172
172
|
|
173
|
-
|
173
|
+
The aggregation algorithm is roughly equivalent to the following pseudo code:
|
174
174
|
|
175
175
|
``` ruby
|
176
176
|
trap('PROF') do
|
@@ -189,16 +189,16 @@ trap('PROF') do
|
|
189
189
|
end
|
190
190
|
```
|
191
191
|
|
192
|
-
|
192
|
+
This technique builds up an incremental call graph from the samples. On any given frame,
|
193
193
|
the sum of the outbound edge weights is equal to total samples collected on that frame
|
194
194
|
(`frame.total_samples == frame.edges.values.sum`).
|
195
195
|
|
196
196
|
## Reporting
|
197
197
|
|
198
|
-
|
199
|
-
-
|
200
|
-
-
|
201
|
-
-
|
198
|
+
Multiple reporting modes are supported:
|
199
|
+
- Text
|
200
|
+
- Dotgraph
|
201
|
+
- Source annotation
|
202
202
|
|
203
203
|
### `StackProf::Report.new(data).print_text`
|
204
204
|
|
@@ -217,8 +217,6 @@ multiple reporting modes are supported:
|
|
217
217
|
|
218
218
|
### `StackProf::Report.new(data).print_graphviz`
|
219
219
|
|
220
|
-
![](http://cl.ly/image/2t3l2q0l0B0A/content)
|
221
|
-
|
222
220
|
```
|
223
221
|
digraph profile {
|
224
222
|
70346498324780 [size=23.5531914893617] [fontsize=23.5531914893617] [shape=box] [label="A#pow\n91 (48.4%)\r"];
|
@@ -265,8 +263,8 @@ block in A#math (/Users/tmm1/code/stackprof/sample.rb:21)
|
|
265
263
|
|
266
264
|
## Usage
|
267
265
|
|
268
|
-
|
269
|
-
|
266
|
+
The profiler is compiled as a C-extension and exposes a simple api: `StackProf.run(mode: [:cpu|:wall|:object])`.
|
267
|
+
The `run` method takes a block of code and returns a profile as a simple hash.
|
270
268
|
|
271
269
|
``` ruby
|
272
270
|
# sample after every 1ms of cpu activity
|
@@ -275,12 +273,12 @@ profile = StackProf.run(mode: :cpu, interval: 1000) do
|
|
275
273
|
end
|
276
274
|
```
|
277
275
|
|
278
|
-
|
279
|
-
(as json/marshal for example) for later processing.
|
276
|
+
This profile data structure is part of the public API, and is intended to be saved
|
277
|
+
(as json/marshal for example) for later processing. The reports above can be generated
|
280
278
|
by passing this structure into `StackProf::Report.new`.
|
281
279
|
|
282
|
-
|
283
|
-
identifying information such as its name, file and line.
|
280
|
+
The format itself is very simple. It contains a header and a list of frames. Each frame has a unique ID and
|
281
|
+
identifying information such as its name, file, and line. The frame also contains sampling data, including per-line
|
284
282
|
samples, and a list of relationships to other frames represented as weighted edges.
|
285
283
|
|
286
284
|
``` ruby
|
@@ -307,20 +305,21 @@ samples, and a list of relationships to other frames represented as weighted edg
|
|
307
305
|
:lines=>{8=>1}},
|
308
306
|
```
|
309
307
|
|
310
|
-
|
308
|
+
Above, `A#pow` was involved in 91 samples, and in all cases it was at the top of the stack on line 12.
|
311
309
|
|
312
|
-
`A#initialize` was in 185 samples, but it was at the top of the stack in only 1 sample.
|
313
|
-
divided up between its callee edges.
|
310
|
+
`A#initialize` was in 185 samples, but it was at the top of the stack in only 1 sample. The rest of the samples are
|
311
|
+
divided up between its callee edges. All 91 calls to `A#pow` came from `A#initialize`, as seen by the edge numbered
|
314
312
|
`70346498324780`.
|
315
313
|
|
316
314
|
## Advanced usage
|
317
315
|
|
318
|
-
|
319
|
-
multiple start
|
316
|
+
The profiler can be started and stopped manually. Results are accumulated until retrieval, across
|
317
|
+
multiple `start`/`stop` invocations.
|
320
318
|
|
321
319
|
``` ruby
|
322
|
-
StackProf.running?
|
320
|
+
StackProf.running? # => false
|
323
321
|
StackProf.start(mode: :cpu)
|
322
|
+
StackProf.running? # => true
|
324
323
|
StackProf.stop
|
325
324
|
StackProf.results('/tmp/some.file')
|
326
325
|
```
|
@@ -331,14 +330,14 @@ StackProf.results('/tmp/some.file')
|
|
331
330
|
|
332
331
|
Option | Meaning
|
333
332
|
------- | ---------
|
334
|
-
`mode` |
|
335
|
-
`out` |
|
336
|
-
`interval` |
|
333
|
+
`mode` | Mode of sampling: `:cpu`, `:wall`, `:object`, or `:custom` [c.f.](#sampling)
|
334
|
+
`out` | The target file, which will be overwritten
|
335
|
+
`interval` | Mode-relative sample rate [c.f.](#sampling)
|
337
336
|
`ignore_gc` | Ignore garbage collection frames
|
338
|
-
`aggregate` |
|
339
|
-
`raw` |
|
340
|
-
`metadata` |
|
341
|
-
`save_every`| (
|
337
|
+
`aggregate` | Defaults: `true` - if `false` disables [aggregation](#aggregation)
|
338
|
+
`raw` | Defaults `false` - if `true` collects the extra data required by the `--flamegraph` and `--stackcollapse` report types
|
339
|
+
`metadata` | Defaults to `{}`. Must be a `Hash`. metadata associated with this profile
|
340
|
+
`save_every`| (Rack middleware only) write the target file after this many requests
|
342
341
|
|
343
342
|
## Todo
|
344
343
|
|
data/Rakefile
CHANGED
@@ -1,31 +1,17 @@
|
|
1
|
-
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require "rake/testtask"
|
2
3
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
GEMSPEC = Gem::Specification::load('stackprof.gemspec')
|
8
|
-
|
9
|
-
require 'rubygems/package_task'
|
10
|
-
Gem::PackageTask.new(GEMSPEC) do |pkg|
|
4
|
+
Rake::TestTask.new(:test) do |t|
|
5
|
+
t.libs << "test"
|
6
|
+
t.libs << "lib"
|
7
|
+
t.test_files = FileList["test/**/test_*.rb"]
|
11
8
|
end
|
12
9
|
|
13
|
-
|
14
|
-
# Ruby Extension
|
15
|
-
# ==========================================================
|
10
|
+
require "rake/extensiontask"
|
16
11
|
|
17
|
-
|
18
|
-
|
19
|
-
ext.lib_dir =
|
12
|
+
Rake::ExtensionTask.new("stackprof") do |ext|
|
13
|
+
ext.ext_dir = "ext/stackprof"
|
14
|
+
ext.lib_dir = "lib/stackprof"
|
20
15
|
end
|
21
|
-
task :build => :compile
|
22
16
|
|
23
|
-
|
24
|
-
# Testing
|
25
|
-
# ==========================================================
|
26
|
-
|
27
|
-
require 'rake/testtask'
|
28
|
-
Rake::TestTask.new 'test' do |t|
|
29
|
-
t.test_files = FileList['test/test_*.rb']
|
30
|
-
end
|
31
|
-
task :test => :build
|
17
|
+
task default: %i(compile test)
|
data/ext/stackprof/stackprof.c
CHANGED
@@ -22,6 +22,14 @@
|
|
22
22
|
#define FAKE_FRAME_MARK INT2FIX(1)
|
23
23
|
#define FAKE_FRAME_SWEEP INT2FIX(2)
|
24
24
|
|
25
|
+
/*
|
26
|
+
* As of Ruby 3.0, it should be safe to read stack frames at any time
|
27
|
+
* See https://github.com/ruby/ruby/commit/0e276dc458f94d9d79a0f7c7669bde84abe80f21
|
28
|
+
*/
|
29
|
+
#if RUBY_API_VERSION_MAJOR < 3
|
30
|
+
#define USE_POSTPONED_JOB
|
31
|
+
#endif
|
32
|
+
|
25
33
|
static const char *fake_frame_cstrs[] = {
|
26
34
|
"(garbage collection)",
|
27
35
|
"(marking)",
|
@@ -596,31 +604,30 @@ stackprof_record_gc_samples()
|
|
596
604
|
static void
|
597
605
|
stackprof_gc_job_handler(void *data)
|
598
606
|
{
|
599
|
-
static int in_signal_handler = 0;
|
600
|
-
if (in_signal_handler) return;
|
601
607
|
if (!_stackprof.running) return;
|
602
608
|
|
603
|
-
in_signal_handler++;
|
604
609
|
stackprof_record_gc_samples();
|
605
|
-
in_signal_handler--;
|
606
610
|
}
|
607
611
|
|
608
612
|
static void
|
609
613
|
stackprof_job_handler(void *data)
|
610
614
|
{
|
611
|
-
static int in_signal_handler = 0;
|
612
|
-
if (in_signal_handler) return;
|
613
615
|
if (!_stackprof.running) return;
|
614
616
|
|
615
|
-
in_signal_handler++;
|
616
617
|
stackprof_record_sample();
|
617
|
-
in_signal_handler--;
|
618
618
|
}
|
619
619
|
|
620
620
|
static void
|
621
621
|
stackprof_signal_handler(int sig, siginfo_t *sinfo, void *ucontext)
|
622
622
|
{
|
623
|
+
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
|
624
|
+
|
623
625
|
_stackprof.overall_signals++;
|
626
|
+
|
627
|
+
if (!_stackprof.running) return;
|
628
|
+
if (!ruby_native_thread_p()) return;
|
629
|
+
if (pthread_mutex_trylock(&lock)) return;
|
630
|
+
|
624
631
|
if (!_stackprof.ignore_gc && rb_during_gc()) {
|
625
632
|
VALUE mode = rb_gc_latest_gc_info(sym_state);
|
626
633
|
if (mode == sym_marking) {
|
@@ -631,8 +638,13 @@ stackprof_signal_handler(int sig, siginfo_t *sinfo, void *ucontext)
|
|
631
638
|
_stackprof.unrecorded_gc_samples++;
|
632
639
|
rb_postponed_job_register_one(0, stackprof_gc_job_handler, (void*)0);
|
633
640
|
} else {
|
641
|
+
#ifdef USE_POSTPONED_JOB
|
634
642
|
rb_postponed_job_register_one(0, stackprof_job_handler, (void*)0);
|
643
|
+
#else
|
644
|
+
stackprof_job_handler(0);
|
645
|
+
#endif
|
635
646
|
}
|
647
|
+
pthread_mutex_unlock(&lock);
|
636
648
|
}
|
637
649
|
|
638
650
|
static void
|
data/lib/stackprof.rb
CHANGED
data/lib/stackprof/report.rb
CHANGED
@@ -445,7 +445,7 @@ module StackProf
|
|
445
445
|
call, total = info.values_at(:samples, :total_samples)
|
446
446
|
break if total < node_minimum || (limit && index >= limit)
|
447
447
|
|
448
|
-
sample = ''
|
448
|
+
sample = ''.dup
|
449
449
|
sample << "#{call} (%2.1f%%)\\rof " % (call*100.0/overall_samples) if call < total
|
450
450
|
sample << "#{total} (%2.1f%%)\\r" % (total*100.0/overall_samples)
|
451
451
|
fontsize = (1.0 * call / max_samples) * 28 + 10
|
data/stackprof.gemspec
CHANGED
data/test/test_stackprof.rb
CHANGED
@@ -39,16 +39,30 @@ class StackProfTest < MiniTest::Test
|
|
39
39
|
end
|
40
40
|
assert_equal :object, profile[:mode]
|
41
41
|
assert_equal 1, profile[:interval]
|
42
|
-
|
42
|
+
if RUBY_VERSION >= '3'
|
43
|
+
assert_equal 4, profile[:samples]
|
44
|
+
else
|
45
|
+
assert_equal 2, profile[:samples]
|
46
|
+
end
|
43
47
|
|
44
48
|
frame = profile[:frames].values.first
|
45
49
|
assert_includes frame[:name], "StackProfTest#test_object_allocation"
|
46
50
|
assert_equal 2, frame[:samples]
|
47
51
|
assert_includes [profile_base_line - 2, profile_base_line], frame[:line]
|
48
|
-
|
49
|
-
|
52
|
+
if RUBY_VERSION >= '3'
|
53
|
+
assert_equal [2, 1], frame[:lines][profile_base_line+1]
|
54
|
+
assert_equal [2, 1], frame[:lines][profile_base_line+2]
|
55
|
+
else
|
56
|
+
assert_equal [1, 1], frame[:lines][profile_base_line+1]
|
57
|
+
assert_equal [1, 1], frame[:lines][profile_base_line+2]
|
58
|
+
end
|
50
59
|
frame = profile[:frames].values[1] if RUBY_VERSION < '2.3'
|
51
|
-
|
60
|
+
|
61
|
+
if RUBY_VERSION >= '3'
|
62
|
+
assert_equal [4, 0], frame[:lines][profile_base_line]
|
63
|
+
else
|
64
|
+
assert_equal [2, 0], frame[:lines][profile_base_line]
|
65
|
+
end
|
52
66
|
end
|
53
67
|
|
54
68
|
def test_object_allocation_interval
|
@@ -64,7 +78,8 @@ class StackProfTest < MiniTest::Test
|
|
64
78
|
end
|
65
79
|
|
66
80
|
assert_operator profile[:samples], :>=, 1
|
67
|
-
|
81
|
+
offset = RUBY_VERSION >= '3' ? 1 : 0
|
82
|
+
frame = profile[:frames].values[offset]
|
68
83
|
assert_includes frame[:name], "StackProfTest#math"
|
69
84
|
end
|
70
85
|
|
@@ -74,7 +89,11 @@ class StackProfTest < MiniTest::Test
|
|
74
89
|
end
|
75
90
|
|
76
91
|
frame = profile[:frames].values.first
|
77
|
-
|
92
|
+
if RUBY_VERSION >= '3'
|
93
|
+
assert_equal "IO.select", frame[:name]
|
94
|
+
else
|
95
|
+
assert_equal "StackProfTest#idle", frame[:name]
|
96
|
+
end
|
78
97
|
assert_in_delta 200, frame[:samples], 25
|
79
98
|
end
|
80
99
|
|
@@ -89,10 +108,16 @@ class StackProfTest < MiniTest::Test
|
|
89
108
|
assert_equal :custom, profile[:mode]
|
90
109
|
assert_equal 10, profile[:samples]
|
91
110
|
|
92
|
-
|
111
|
+
offset = RUBY_VERSION >= '3' ? 1 : 0
|
112
|
+
frame = profile[:frames].values[offset]
|
93
113
|
assert_includes frame[:name], "StackProfTest#test_custom"
|
94
114
|
assert_includes [profile_base_line-2, profile_base_line+1], frame[:line]
|
95
|
-
|
115
|
+
|
116
|
+
if RUBY_VERSION >= '3'
|
117
|
+
assert_equal [10, 0], frame[:lines][profile_base_line+2]
|
118
|
+
else
|
119
|
+
assert_equal [10, 10], frame[:lines][profile_base_line+2]
|
120
|
+
end
|
96
121
|
end
|
97
122
|
|
98
123
|
def test_raw
|
@@ -105,7 +130,9 @@ class StackProfTest < MiniTest::Test
|
|
105
130
|
raw = profile[:raw]
|
106
131
|
assert_equal 10, raw[-1]
|
107
132
|
assert_equal raw[0] + 2, raw.size
|
108
|
-
|
133
|
+
|
134
|
+
offset = RUBY_VERSION >= '3' ? -3 : -2
|
135
|
+
assert_includes profile[:frames][raw[offset]][:name], 'StackProfTest#test_raw'
|
109
136
|
assert_equal 10, profile[:raw_timestamp_deltas].size
|
110
137
|
end
|
111
138
|
|
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.17
|
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: 2021-05-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake-compiler
|
@@ -63,10 +63,9 @@ extensions:
|
|
63
63
|
- ext/stackprof/extconf.rb
|
64
64
|
extra_rdoc_files: []
|
65
65
|
files:
|
66
|
+
- ".github/workflows/ci.yml"
|
66
67
|
- ".gitignore"
|
67
|
-
- ".travis.yml"
|
68
68
|
- CHANGELOG.md
|
69
|
-
- Dockerfile
|
70
69
|
- Gemfile
|
71
70
|
- LICENSE
|
72
71
|
- README.md
|
@@ -95,9 +94,9 @@ licenses:
|
|
95
94
|
- MIT
|
96
95
|
metadata:
|
97
96
|
bug_tracker_uri: https://github.com/tmm1/stackprof/issues
|
98
|
-
changelog_uri: https://github.com/tmm1/stackprof/blob/v0.2.
|
99
|
-
documentation_uri: https://www.rubydoc.info/gems/stackprof/0.2.
|
100
|
-
source_code_uri: https://github.com/tmm1/stackprof/tree/v0.2.
|
97
|
+
changelog_uri: https://github.com/tmm1/stackprof/blob/v0.2.17/CHANGELOG.md
|
98
|
+
documentation_uri: https://www.rubydoc.info/gems/stackprof/0.2.17
|
99
|
+
source_code_uri: https://github.com/tmm1/stackprof/tree/v0.2.17
|
101
100
|
post_install_message:
|
102
101
|
rdoc_options: []
|
103
102
|
require_paths:
|
@@ -113,7 +112,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
113
112
|
- !ruby/object:Gem::Version
|
114
113
|
version: '0'
|
115
114
|
requirements: []
|
116
|
-
rubygems_version: 3.
|
115
|
+
rubygems_version: 3.1.2
|
117
116
|
signing_key:
|
118
117
|
specification_version: 4
|
119
118
|
summary: sampling callstack-profiler for ruby 2.2+
|
data/.travis.yml
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
sudo: required
|
2
|
-
|
3
|
-
services:
|
4
|
-
- docker
|
5
|
-
|
6
|
-
language: general
|
7
|
-
|
8
|
-
env:
|
9
|
-
matrix:
|
10
|
-
- RVM_RUBY_VERSION=2.2
|
11
|
-
- RVM_RUBY_VERSION=2.3
|
12
|
-
- RVM_RUBY_VERSION=2.4
|
13
|
-
- RVM_RUBY_VERSION=2.5
|
14
|
-
- RVM_RUBY_VERSION=2.6
|
15
|
-
- RVM_RUBY_VERSION=ruby-head
|
16
|
-
|
17
|
-
before_install:
|
18
|
-
- sudo docker build -t stackprof-$RVM_RUBY_VERSION --build-arg=RVM_RUBY_VERSION=$RVM_RUBY_VERSION .
|
19
|
-
|
20
|
-
script:
|
21
|
-
- sudo docker run --name stackprof-$RVM_RUBY_VERSION stackprof-$RVM_RUBY_VERSION
|
data/Dockerfile
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
FROM ubuntu:16.04
|
2
|
-
ARG DEBIAN_FRONTEND=noninteractive
|
3
|
-
RUN apt-get update -q && \
|
4
|
-
apt-get install -qy \
|
5
|
-
curl ca-certificates gnupg2 dirmngr build-essential \
|
6
|
-
gawk git autoconf automake pkg-config \
|
7
|
-
bison libffi-dev libgdbm-dev libncurses5-dev libsqlite3-dev libtool \
|
8
|
-
libyaml-dev sqlite3 zlib1g-dev libgmp-dev libreadline-dev libssl-dev \
|
9
|
-
ruby --no-install-recommends && \
|
10
|
-
apt-get clean
|
11
|
-
|
12
|
-
RUN gpg2 --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB
|
13
|
-
RUN curl -sSL https://get.rvm.io | bash -s
|
14
|
-
ARG RVM_RUBY_VERSION=ruby-head
|
15
|
-
RUN /bin/bash -l -c "echo $RVM_RUBY_VERSION"
|
16
|
-
RUN /bin/bash -l -c ". /etc/profile.d/rvm.sh && rvm install $RVM_RUBY_VERSION --binary || rvm install $RVM_RUBY_VERSION"
|
17
|
-
ADD . /stackprof/
|
18
|
-
WORKDIR /stackprof/
|
19
|
-
RUN /bin/bash -l -c ". /etc/profile.d/rvm.sh && gem install bundler:1.16.0"
|
20
|
-
RUN /bin/bash -l -c ". /etc/profile.d/rvm.sh && bundle install"
|
21
|
-
CMD /bin/bash -l -c ". /etc/profile.d/rvm.sh && bundle exec rake"
|