vernier 1.10.0 → 1.11.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.
- checksums.yaml +4 -4
- data/.ruby-version +1 -1
- data/Gemfile +2 -0
- data/ext/vernier/heap_tracker.cc +3 -0
- data/lib/vernier/collector.rb +2 -0
- data/lib/vernier/output/cpuprofile.rb +6 -0
- data/lib/vernier/output/file_listing.rb +56 -27
- data/lib/vernier/output/firefox.rb +66 -36
- data/lib/vernier/output/top.rb +8 -4
- data/lib/vernier/output_helpers.rb +33 -0
- data/lib/vernier/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6e8d610b954485d3bccefa47408932dddd5806b618caa2958d689f8c0c8fbb3d
|
|
4
|
+
data.tar.gz: 2423bf5e06dd1168e21f0a5063050e897137c37bd09ce68a540af9d84b0a7546
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 942b097d843b63457650254b2e9717698939df9ee40c02ff367832d344121e6ffdafffbc2e0824d70229bf5d4187d1cf0eb64491402a4c54c4c5f6dd8fb0b98f
|
|
7
|
+
data.tar.gz: 2f710c6b9eeb8e4e352290902aed1a4142ea5b48df7039ee49de66dc7c9f7411e25cb77319addba69a15f072f08b3820a51535fe19070a4e77341aa6c000a57b
|
data/.ruby-version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
4.0
|
data/Gemfile
CHANGED
data/ext/vernier/heap_tracker.cc
CHANGED
data/lib/vernier/collector.rb
CHANGED
|
@@ -29,6 +29,7 @@ module Vernier
|
|
|
29
29
|
result.instance_variable_set(:@threads, {
|
|
30
30
|
0 => {
|
|
31
31
|
tid: 0,
|
|
32
|
+
is_main: true,
|
|
32
33
|
name: "custom",
|
|
33
34
|
started_at: @started_at,
|
|
34
35
|
samples: @samples,
|
|
@@ -80,6 +81,7 @@ module Vernier
|
|
|
80
81
|
result.instance_variable_set(:@threads, {
|
|
81
82
|
0 => {
|
|
82
83
|
tid: 0,
|
|
84
|
+
is_main: true,
|
|
83
85
|
name: "retained memory",
|
|
84
86
|
started_at: @started_at,
|
|
85
87
|
samples: samples,
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
require "json"
|
|
2
2
|
|
|
3
|
+
require_relative "../output_helpers"
|
|
4
|
+
|
|
3
5
|
module Vernier
|
|
4
6
|
module Output
|
|
5
7
|
class Cpuprofile
|
|
8
|
+
include OutputHelpers
|
|
9
|
+
|
|
6
10
|
def initialize(profile)
|
|
7
11
|
@profile = profile
|
|
8
12
|
end
|
|
@@ -98,7 +102,9 @@ module Vernier
|
|
|
98
102
|
line = stack_table.frame_line_no(frame_idx) - 1
|
|
99
103
|
|
|
100
104
|
func_name = stack_table.func_name(func_idx)
|
|
105
|
+
func_name = sanitize_string(func_name) if func_name
|
|
101
106
|
filename = stack_table.func_filename(func_idx)
|
|
107
|
+
filename = sanitize_string(filename) if filename
|
|
102
108
|
|
|
103
109
|
node_id = nodes.length
|
|
104
110
|
node = {
|
|
@@ -1,23 +1,19 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative "filename_filter"
|
|
4
|
+
require_relative "../output_helpers"
|
|
4
5
|
require "cgi/escape"
|
|
5
6
|
|
|
6
7
|
module Vernier
|
|
7
8
|
module Output
|
|
8
9
|
class FileListing
|
|
10
|
+
include OutputHelpers
|
|
11
|
+
|
|
9
12
|
class SamplesByLocation
|
|
10
13
|
attr_accessor :self, :total
|
|
11
14
|
def initialize
|
|
12
15
|
@self = @total = 0
|
|
13
16
|
end
|
|
14
|
-
|
|
15
|
-
def +(other)
|
|
16
|
-
ret = SamplesByLocation.new
|
|
17
|
-
ret.self = @self + other.self
|
|
18
|
-
ret.total = @total + other.total
|
|
19
|
-
ret
|
|
20
|
-
end
|
|
21
17
|
end
|
|
22
18
|
|
|
23
19
|
def initialize(profile)
|
|
@@ -25,6 +21,8 @@ module Vernier
|
|
|
25
21
|
end
|
|
26
22
|
|
|
27
23
|
def samples_by_file
|
|
24
|
+
return @samples_by_file if defined?(@samples_by_file)
|
|
25
|
+
|
|
28
26
|
thread = @profile.main_thread
|
|
29
27
|
if Hash === thread
|
|
30
28
|
# live profile
|
|
@@ -38,22 +36,9 @@ module Vernier
|
|
|
38
36
|
weights = thread[:weights]
|
|
39
37
|
samples = thread[:samples]
|
|
40
38
|
|
|
41
|
-
|
|
42
|
-
h[k] = SamplesByLocation.new
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
samples.zip(weights).each do |stack_idx, weight|
|
|
46
|
-
# self time
|
|
47
|
-
top_frame_index = stack_table.stack_frame_idx(stack_idx)
|
|
48
|
-
self_samples_by_frame[top_frame_index].self += weight
|
|
39
|
+
stack_weights = collapse_stack_weights(samples, weights)
|
|
49
40
|
|
|
50
|
-
|
|
51
|
-
while stack_idx
|
|
52
|
-
frame_idx = stack_table.stack_frame_idx(stack_idx)
|
|
53
|
-
self_samples_by_frame[frame_idx].total += weight
|
|
54
|
-
stack_idx = stack_table.stack_parent_idx(stack_idx)
|
|
55
|
-
end
|
|
56
|
-
end
|
|
41
|
+
self_by_frame, total_by_frame = frame_weights(stack_table, stack_weights)
|
|
57
42
|
|
|
58
43
|
samples_by_file = Hash.new do |h, k|
|
|
59
44
|
h[k] = Hash.new do |h2, k2|
|
|
@@ -61,19 +46,64 @@ module Vernier
|
|
|
61
46
|
end
|
|
62
47
|
end
|
|
63
48
|
|
|
64
|
-
|
|
49
|
+
self_by_frame.each_with_index do |self_weight, frame|
|
|
50
|
+
total_weight = total_by_frame[frame]
|
|
51
|
+
next if self_weight == 0 && total_weight == 0
|
|
52
|
+
|
|
65
53
|
line = stack_table.frame_line_no(frame)
|
|
66
54
|
func_index = stack_table.frame_func_idx(frame)
|
|
67
55
|
filename = stack_table.func_filename(func_index)
|
|
68
56
|
|
|
69
|
-
samples_by_file[filename][line]
|
|
57
|
+
location = samples_by_file[filename][line]
|
|
58
|
+
location.self += self_weight
|
|
59
|
+
location.total += total_weight
|
|
70
60
|
end
|
|
71
61
|
|
|
72
|
-
samples_by_file.transform_keys! do |filename|
|
|
62
|
+
@samples_by_file = samples_by_file.transform_keys! do |filename|
|
|
73
63
|
filename_filter.call(filename)
|
|
74
64
|
end
|
|
75
65
|
end
|
|
76
66
|
|
|
67
|
+
# Returns [self_weight, total_weight] arrays indexed by frame, from a
|
|
68
|
+
# hash of per-stack weights.
|
|
69
|
+
#
|
|
70
|
+
# The stack table is a prefix tree whose parent is always interned
|
|
71
|
+
# before its children (parent idx < child idx), so total weights are
|
|
72
|
+
# accumulated bottom-up in a single reverse pass.
|
|
73
|
+
private def frame_weights(stack_table, stack_weights)
|
|
74
|
+
# Scatter the sparse weights into an array indexed by stack.
|
|
75
|
+
stack_totals = Array.new(stack_table.stack_count, 0)
|
|
76
|
+
stack_weights.each do |stack_idx, weight|
|
|
77
|
+
stack_totals[stack_idx] = weight
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Accumulate each stack's total into its parent, children first,
|
|
81
|
+
# so a single descending pass completes every subtree's total.
|
|
82
|
+
(stack_totals.length - 1).downto(0) do |stack_idx|
|
|
83
|
+
parent_idx = stack_table.stack_parent_idx(stack_idx)
|
|
84
|
+
next unless parent_idx
|
|
85
|
+
|
|
86
|
+
if parent_idx >= stack_idx
|
|
87
|
+
raise "Invalid profile: stack table is not parent-before-child ordered"
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
stack_totals[parent_idx] += stack_totals[stack_idx]
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
self_by_frame = Array.new(stack_table.frame_count, 0)
|
|
94
|
+
total_by_frame = Array.new(stack_table.frame_count, 0)
|
|
95
|
+
stack_weights.each do |stack_idx, weight|
|
|
96
|
+
self_by_frame[stack_table.stack_frame_idx(stack_idx)] += weight
|
|
97
|
+
end
|
|
98
|
+
stack_totals.each_with_index do |total, stack_idx|
|
|
99
|
+
next if total == 0
|
|
100
|
+
|
|
101
|
+
total_by_frame[stack_table.stack_frame_idx(stack_idx)] += total
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
[self_by_frame, total_by_frame]
|
|
105
|
+
end
|
|
106
|
+
|
|
77
107
|
def output(template: nil)
|
|
78
108
|
output = +""
|
|
79
109
|
|
|
@@ -98,8 +128,7 @@ module Vernier
|
|
|
98
128
|
end
|
|
99
129
|
|
|
100
130
|
def total
|
|
101
|
-
|
|
102
|
-
thread[:weights].sum
|
|
131
|
+
@total ||= @profile.main_thread[:weights].sum
|
|
103
132
|
end
|
|
104
133
|
|
|
105
134
|
def format_file(output, filename, all_samples, total:)
|
|
@@ -4,6 +4,7 @@ require "json"
|
|
|
4
4
|
require "rbconfig"
|
|
5
5
|
|
|
6
6
|
require_relative "filename_filter"
|
|
7
|
+
require_relative "../output_helpers"
|
|
7
8
|
|
|
8
9
|
module Vernier
|
|
9
10
|
module Output
|
|
@@ -267,6 +268,13 @@ module Vernier
|
|
|
267
268
|
end
|
|
268
269
|
|
|
269
270
|
class Thread
|
|
271
|
+
include OutputHelpers
|
|
272
|
+
|
|
273
|
+
SAMPLE_CATEGORY_NAMES = {
|
|
274
|
+
1 => "Idle",
|
|
275
|
+
2 => "Stalled"
|
|
276
|
+
}.freeze
|
|
277
|
+
|
|
270
278
|
attr_reader :profile, :is_start
|
|
271
279
|
|
|
272
280
|
def initialize(ruby_thread_id, profile, categorizer, name:, tid:, samples:, weights:, timestamps: nil, sample_categories: nil, markers:, started_at:, stopped_at: nil, allocations: nil, is_main: nil, is_start: nil)
|
|
@@ -355,6 +363,31 @@ module Vernier
|
|
|
355
363
|
@frame_subcategories = @stack_table_hash[:frame_table].fetch(:func).map do |func_idx|
|
|
356
364
|
func_subcategories[func_idx]
|
|
357
365
|
end
|
|
366
|
+
|
|
367
|
+
@sample_category_idx = SAMPLE_CATEGORY_NAMES.transform_values do |name|
|
|
368
|
+
@categorizer.get_category(name).idx
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
@samples.zip(@sample_categories).each do |sample, raw_category|
|
|
372
|
+
next if raw_category == 0
|
|
373
|
+
|
|
374
|
+
@categorized_stacks[[sample, raw_category]]
|
|
375
|
+
end
|
|
376
|
+
|
|
377
|
+
base_stack_frames = @stack_table_hash[:stack_table].fetch(:frame)
|
|
378
|
+
base_frame_count = @stack_table_hash[:frame_table].fetch(:func).size
|
|
379
|
+
@extra_frames = []
|
|
380
|
+
@categorized_frame_map = {}
|
|
381
|
+
|
|
382
|
+
@categorized_stacks.each_key do |(stack, raw_category)|
|
|
383
|
+
original_frame_idx = base_stack_frames[stack]
|
|
384
|
+
key = [original_frame_idx, raw_category]
|
|
385
|
+
next if @categorized_frame_map.key?(key)
|
|
386
|
+
|
|
387
|
+
new_frame_idx = base_frame_count + @extra_frames.size
|
|
388
|
+
@categorized_frame_map[key] = new_frame_idx
|
|
389
|
+
@extra_frames << [original_frame_idx, @sample_category_idx[raw_category]]
|
|
390
|
+
end
|
|
358
391
|
end
|
|
359
392
|
|
|
360
393
|
def categorize_filename(filename)
|
|
@@ -377,7 +410,7 @@ module Vernier
|
|
|
377
410
|
def find_category_and_subcategory(filename, categories)
|
|
378
411
|
categories.each do |category_name|
|
|
379
412
|
category = @categorizer.get_category(category_name)
|
|
380
|
-
subcategory = category.subcategories.detect {|c| c.matches?(filename) }&.idx
|
|
413
|
+
subcategory = category.subcategories.detect { |c| c.matches?(filename) }&.idx
|
|
381
414
|
return category, subcategory if subcategory
|
|
382
415
|
end
|
|
383
416
|
[nil, nil]
|
|
@@ -430,7 +463,7 @@ module Vernier
|
|
|
430
463
|
categories = []
|
|
431
464
|
data = []
|
|
432
465
|
|
|
433
|
-
@markers.
|
|
466
|
+
@markers.each do |(_, name, start, finish, phase, datum)|
|
|
434
467
|
string_indexes << @strings[name]
|
|
435
468
|
start_times << (start / 1_000_000.0)
|
|
436
469
|
|
|
@@ -463,12 +496,14 @@ module Vernier
|
|
|
463
496
|
end
|
|
464
497
|
|
|
465
498
|
def allocations_table
|
|
466
|
-
return nil
|
|
499
|
+
return nil unless @allocations
|
|
500
|
+
|
|
467
501
|
samples, weights, timestamps = @allocations.values_at(:samples, :weights, :timestamps)
|
|
468
|
-
return nil if samples.
|
|
502
|
+
return nil if samples.empty?
|
|
503
|
+
|
|
469
504
|
size = samples.size
|
|
470
505
|
timestamps = timestamps.map { _1 / 1_000_000.0 }
|
|
471
|
-
|
|
506
|
+
{
|
|
472
507
|
"time": timestamps,
|
|
473
508
|
"className": ["Object"]*size,
|
|
474
509
|
"typeName": ["JSObject"]*size,
|
|
@@ -478,7 +513,6 @@ module Vernier
|
|
|
478
513
|
"stack": samples,
|
|
479
514
|
"length": size
|
|
480
515
|
}
|
|
481
|
-
ret
|
|
482
516
|
end
|
|
483
517
|
|
|
484
518
|
def samples_table
|
|
@@ -518,21 +552,22 @@ module Vernier
|
|
|
518
552
|
end
|
|
519
553
|
|
|
520
554
|
def stack_table
|
|
521
|
-
|
|
555
|
+
base_frames = @stack_table_hash[:stack_table].fetch(:frame)
|
|
556
|
+
frames = base_frames.dup
|
|
522
557
|
prefixes = @stack_table_hash[:stack_table].fetch(:parent).dup
|
|
523
|
-
categories
|
|
524
|
-
subcategories
|
|
558
|
+
categories = frames.map { |idx| @frame_categories[idx].idx }
|
|
559
|
+
subcategories = frames.map { |idx| @frame_subcategories[idx] }
|
|
525
560
|
|
|
526
|
-
@categorized_stacks.each_key do |(stack,
|
|
527
|
-
|
|
561
|
+
@categorized_stacks.each_key do |(stack, raw_category)|
|
|
562
|
+
original_frame_idx = base_frames[stack]
|
|
563
|
+
frames << @categorized_frame_map[[original_frame_idx, raw_category]]
|
|
528
564
|
prefixes << prefixes[stack]
|
|
529
|
-
categories <<
|
|
565
|
+
categories << @sample_category_idx[raw_category]
|
|
530
566
|
subcategories << 0
|
|
531
567
|
end
|
|
532
568
|
|
|
533
|
-
size
|
|
534
|
-
|
|
535
|
-
raise unless prefixes.size == size
|
|
569
|
+
raise unless prefixes.size == frames.size
|
|
570
|
+
|
|
536
571
|
{
|
|
537
572
|
frame: frames,
|
|
538
573
|
category: categories,
|
|
@@ -543,18 +578,27 @@ module Vernier
|
|
|
543
578
|
end
|
|
544
579
|
|
|
545
580
|
def frame_table
|
|
546
|
-
funcs = @stack_table_hash[:frame_table].fetch(:func)
|
|
547
|
-
lines = @stack_table_hash[:frame_table].fetch(:line)
|
|
581
|
+
funcs = @stack_table_hash[:frame_table].fetch(:func).dup
|
|
582
|
+
lines = @stack_table_hash[:frame_table].fetch(:line).dup
|
|
548
583
|
raise unless lines.size == funcs.size
|
|
549
584
|
|
|
585
|
+
categories = @frame_categories.map(&:idx)
|
|
586
|
+
subcategories = @frame_subcategories.dup
|
|
587
|
+
implementations = @frame_implementations.dup
|
|
588
|
+
|
|
589
|
+
@extra_frames.each do |(frame_idx, category_idx)|
|
|
590
|
+
funcs << funcs[frame_idx]
|
|
591
|
+
lines << lines[frame_idx]
|
|
592
|
+
categories << category_idx
|
|
593
|
+
subcategories << 0
|
|
594
|
+
implementations << implementations[frame_idx]
|
|
595
|
+
end
|
|
596
|
+
|
|
550
597
|
size = funcs.size
|
|
551
598
|
none = [nil] * size
|
|
552
599
|
default = [0] * size
|
|
553
600
|
unidentified = [-1] * size
|
|
554
601
|
|
|
555
|
-
categories = @frame_categories.map(&:idx)
|
|
556
|
-
subcategories = @frame_subcategories
|
|
557
|
-
|
|
558
602
|
{
|
|
559
603
|
address: unidentified,
|
|
560
604
|
inlineDepth: default,
|
|
@@ -563,7 +607,7 @@ module Vernier
|
|
|
563
607
|
func: funcs,
|
|
564
608
|
nativeSymbol: none,
|
|
565
609
|
innerWindowID: none,
|
|
566
|
-
implementation:
|
|
610
|
+
implementation: implementations,
|
|
567
611
|
line: lines,
|
|
568
612
|
column: none,
|
|
569
613
|
length: size
|
|
@@ -597,21 +641,7 @@ module Vernier
|
|
|
597
641
|
|
|
598
642
|
def string_table
|
|
599
643
|
@strings.keys.map do |string|
|
|
600
|
-
|
|
601
|
-
string
|
|
602
|
-
elsif string.encoding == Encoding::UTF_8
|
|
603
|
-
if string.valid_encoding?
|
|
604
|
-
string
|
|
605
|
-
else
|
|
606
|
-
string.scrub
|
|
607
|
-
end
|
|
608
|
-
elsif string.encoding == Encoding::BINARY
|
|
609
|
-
# TODO: We might want to guess UTF-8 and escape the binary more explicitly
|
|
610
|
-
string.dup.force_encoding("UTF-8").scrub
|
|
611
|
-
else
|
|
612
|
-
# TODO: ideally we should attempt to properly re-encode here, but right now I think this is dead code
|
|
613
|
-
string.dup.force_encoding("UTF-8").scrub
|
|
614
|
-
end
|
|
644
|
+
sanitize_string(string)
|
|
615
645
|
end
|
|
616
646
|
end
|
|
617
647
|
|
data/lib/vernier/output/top.rb
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative "../output_helpers"
|
|
4
|
+
|
|
3
5
|
module Vernier
|
|
4
6
|
module Output
|
|
5
7
|
class Top
|
|
8
|
+
include OutputHelpers
|
|
9
|
+
|
|
6
10
|
def initialize(profile, row_limit)
|
|
7
11
|
@profile = profile
|
|
8
12
|
@row_limit = row_limit
|
|
@@ -57,10 +61,10 @@ module Vernier
|
|
|
57
61
|
@profile._stack_table
|
|
58
62
|
end
|
|
59
63
|
|
|
60
|
-
|
|
61
|
-
thread[:
|
|
62
|
-
|
|
63
|
-
|
|
64
|
+
samples = thread[:samples]
|
|
65
|
+
weights = thread[:weights]
|
|
66
|
+
|
|
67
|
+
stack_weights = collapse_stack_weights(samples, weights)
|
|
64
68
|
|
|
65
69
|
total = stack_weights.values.sum
|
|
66
70
|
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Vernier
|
|
4
|
+
module OutputHelpers
|
|
5
|
+
# Collapses parallel samples/weights arrays into a hash of total weight
|
|
6
|
+
# per stack index. Retained-mode profiles have one sample per object and
|
|
7
|
+
# many samples share the same stack, so collapsing first keeps later
|
|
8
|
+
# aggregation proportional to the number of unique stacks.
|
|
9
|
+
def collapse_stack_weights(samples, weights)
|
|
10
|
+
stack_weights = Hash.new(0)
|
|
11
|
+
samples.each_with_index do |stack_idx, idx|
|
|
12
|
+
stack_weights[stack_idx] += weights[idx]
|
|
13
|
+
end
|
|
14
|
+
stack_weights
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Returns a string safe to embed in JSON output: valid UTF-8 with any
|
|
18
|
+
# invalid bytes replaced. Method names and paths can carry arbitrary
|
|
19
|
+
# encodings (e.g. BINARY or Shift_JIS source), which would otherwise
|
|
20
|
+
# raise JSON::GeneratorError.
|
|
21
|
+
def sanitize_string(string)
|
|
22
|
+
if string.ascii_only?
|
|
23
|
+
string
|
|
24
|
+
elsif string.encoding == Encoding::UTF_8
|
|
25
|
+
string.valid_encoding? ? string : string.scrub
|
|
26
|
+
else
|
|
27
|
+
# We don't know the real encoding; interpret the bytes as UTF-8
|
|
28
|
+
# and replace anything invalid.
|
|
29
|
+
string.dup.force_encoding(Encoding::UTF_8).scrub
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
data/lib/vernier/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: vernier
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.11.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- John Hawthorn
|
|
@@ -106,6 +106,7 @@ files:
|
|
|
106
106
|
- lib/vernier/output/firefox.rb
|
|
107
107
|
- lib/vernier/output/markdown.rb
|
|
108
108
|
- lib/vernier/output/top.rb
|
|
109
|
+
- lib/vernier/output_helpers.rb
|
|
109
110
|
- lib/vernier/parsed_profile.rb
|
|
110
111
|
- lib/vernier/result.rb
|
|
111
112
|
- lib/vernier/stack_table.rb
|
|
@@ -134,7 +135,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
134
135
|
- !ruby/object:Gem::Version
|
|
135
136
|
version: '0'
|
|
136
137
|
requirements: []
|
|
137
|
-
rubygems_version: 4.0.
|
|
138
|
+
rubygems_version: 4.0.16
|
|
138
139
|
specification_version: 4
|
|
139
140
|
summary: A next generation CRuby profiler
|
|
140
141
|
test_files: []
|