analyzer 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/README.md +36 -0
- data/analyzer.gemspec +22 -0
- data/bin/analyze +28 -0
- data/example_report.png +0 -0
- data/lib/analyzer.rb +107 -0
- data/lib/analyzer/rss.rb +46 -0
- data/lib/analyzer/version.rb +3 -0
- data/lib/templates/gc.rb.erb +61 -0
- data/lib/templates/gnuplot.sh.erb +76 -0
- data/lib/templates/ips.rb.erb +23 -0
- data/lib/templates/rss.rb.erb +49 -0
- metadata +73 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: db0ce1c214e7feed07483dd08de6bbdbc7cb9161
|
4
|
+
data.tar.gz: f233a3477a1295f3264cef66df74c093e887d2c2
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 338cafc259ccd43b47185da1dabbe9ff1a35a36d79c846c851da72302055a169f43cbddf2170a7d2d28fcf2e64868c9df1f89d41f25acefbbf24f0753bd54386
|
7
|
+
data.tar.gz: 65331528d9a72d2e0ccba60521db9673063d25bd177f5349200500b1791cb8a06d339340dcc6f46b68da42e45adf4629372e698d1540dc0adde881430dffd1af
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2017 Jon Bracy
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# Analyzer
|
2
|
+
A Performance analyzer for Ruby
|
3
|
+
|
4
|
+
Synopsis
|
5
|
+
--------
|
6
|
+
|
7
|
+
```bash
|
8
|
+
$ analyze test.rb ...
|
9
|
+
```
|
10
|
+
|
11
|
+
Description
|
12
|
+
-----------
|
13
|
+
|
14
|
+
Analyzer runs the provided ruby file(s) to test Iterations per second,
|
15
|
+
allocations and memory usage.
|
16
|
+
|
17
|
+
The scripts can be a normal ruby script or can be split into two parts by the
|
18
|
+
line `__SETUP__`, everything before will be run once and everything after will
|
19
|
+
be what is tested.
|
20
|
+
|
21
|
+
Options
|
22
|
+
-------
|
23
|
+
|
24
|
+
`-b`, `--bootstrap`: A ruby script to run once before all the test.
|
25
|
+
|
26
|
+
`-l`, `--lib`: A script to be included before the `bootstrap` script and all `test` scripts.
|
27
|
+
|
28
|
+
`-o`, `--output`: The destination for the results. The result is a `png` file.
|
29
|
+
|
30
|
+
|
31
|
+
Example Report
|
32
|
+
--------------
|
33
|
+
|
34
|
+
This report was generated by the command: `analyzer turbostreamer.rb jbuilder.rb -l setup.rb`
|
35
|
+
|
36
|
+
![Viking.js](/example_report.png)
|
data/analyzer.gemspec
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require File.expand_path("../lib/analyzer/version", __FILE__)
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = "analyzer"
|
5
|
+
s.version = Analyzer::VERSION
|
6
|
+
s.licenses = ['MIT']
|
7
|
+
s.authors = ["Jon Bracy"]
|
8
|
+
s.email = ["jonbracy@gmail.com"]
|
9
|
+
s.homepage = "https://github.com/malomalo/analyzer"
|
10
|
+
s.summary = %q{A Performance analyzer for Ruby}
|
11
|
+
s.metadata = { "source_code_uri" => "https://github.com/malomalo/analyzer" }
|
12
|
+
|
13
|
+
s.files = `git ls-files`.split("\n")
|
14
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
15
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
16
|
+
s.require_paths = ["lib"]
|
17
|
+
|
18
|
+
s.required_ruby_version = '>= 2'
|
19
|
+
s.requirements << 'gnuplot'
|
20
|
+
|
21
|
+
s.add_runtime_dependency 'benchmark-ips', '~> 2.7'
|
22
|
+
end
|
data/bin/analyze
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'optparse'
|
3
|
+
require File.expand_path('./../../lib/analyzer', __FILE__)
|
4
|
+
|
5
|
+
options = {}
|
6
|
+
OptionParser.new do |opts|
|
7
|
+
opts.banner = "Usage: analyze [switches] script [script] ... [report.png]"
|
8
|
+
|
9
|
+
opts.on("-b", "--bootstrap SCRIPT", "Script to run before all test") do |v|
|
10
|
+
options[:bootstrap] = v
|
11
|
+
end
|
12
|
+
|
13
|
+
opts.on("-l", "--lib SCRIPT", "Script require before the bootstrap and all test scripts") do |v|
|
14
|
+
options[:lib] = v
|
15
|
+
end
|
16
|
+
|
17
|
+
opts.on("-n x,y,z", Array, "Example 'list' of arguments") do |list|
|
18
|
+
options[:n] = list.map(&:to_i)
|
19
|
+
end
|
20
|
+
|
21
|
+
opts.on('-o', '--output DESTINATION', 'File where output will be placed') do |v|
|
22
|
+
options[:output] = v
|
23
|
+
end
|
24
|
+
end.parse!
|
25
|
+
files = ARGV.clone
|
26
|
+
|
27
|
+
analyzer = Analyzer.new(*files, **options)
|
28
|
+
analyzer.plot(File.expand_path(options[:output] || 'report.png'))
|
data/example_report.png
ADDED
Binary file
|
data/lib/analyzer.rb
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
require 'erb'
|
2
|
+
require 'json'
|
3
|
+
require 'tmpdir'
|
4
|
+
|
5
|
+
class Analyzer
|
6
|
+
|
7
|
+
def initialize(*test_files, bootstrap: nil, lib: nil, n: nil)
|
8
|
+
@bootstrap = bootstrap
|
9
|
+
@lib = lib
|
10
|
+
@n = n
|
11
|
+
@test_files = test_files
|
12
|
+
end
|
13
|
+
|
14
|
+
def key(value)
|
15
|
+
File.basename(value, ".*")
|
16
|
+
end
|
17
|
+
|
18
|
+
def tests
|
19
|
+
@test_files.map{ |f| key(f) }
|
20
|
+
end
|
21
|
+
|
22
|
+
def bootstrap
|
23
|
+
if @bootstrap
|
24
|
+
system("ruby", "-r", "#{File.expand_path(@lib)}", File.expand_path(@bootstrap))
|
25
|
+
if $?.exitstatus > 0
|
26
|
+
exit 1
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def write_results_for(type, dir)
|
32
|
+
Dir.mkdir(File.join(dir, type))
|
33
|
+
@test_files.each do |src|
|
34
|
+
File.open(File.join(dir, type, key(src)), 'w') do |file|
|
35
|
+
send(:"output_#{type}_results", calculate_results_for(type, File.read(src)), file)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def calculate_results_for(type, src)
|
41
|
+
lib = @lib ? File.read(File.expand_path(@lib)) : ''
|
42
|
+
|
43
|
+
if src.index("\n__SETUP__\n")
|
44
|
+
src = src.split("\n__SETUP__\n")
|
45
|
+
setup = src[0]
|
46
|
+
src = src[1]
|
47
|
+
else
|
48
|
+
setup = ''
|
49
|
+
end
|
50
|
+
|
51
|
+
analyzer_dir = File.expand_path("../", __FILE__)
|
52
|
+
template = File.read(File.expand_path("../templates/#{type}.rb.erb", __FILE__))
|
53
|
+
_script = ''
|
54
|
+
ERB.new(template, nil, nil, "_script").result(binding)
|
55
|
+
results = `ruby <<'TESTSCRIPT'\n#{_script}\nTESTSCRIPT`
|
56
|
+
|
57
|
+
if $? == 0
|
58
|
+
JSON.parse(results)
|
59
|
+
else
|
60
|
+
puts results
|
61
|
+
exit
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def output_ips_results(results, output)
|
66
|
+
output.write(results.join("\n"))
|
67
|
+
end
|
68
|
+
|
69
|
+
def output_gc_results(results, output)
|
70
|
+
last_row = results.shift
|
71
|
+
first_row = last_row
|
72
|
+
results.each do |row|
|
73
|
+
output.puts [row[0], row[0] - first_row[0], row[1], row[2], row[1] - last_row[1], row[2] - last_row[2], row[3], row[4], row[3] - last_row[3], row[4] - last_row[4]].join(' ')
|
74
|
+
last_row = row
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def output_rss_results(results, output)
|
79
|
+
last_row = results.shift
|
80
|
+
first_row = last_row
|
81
|
+
results.each do |row|
|
82
|
+
output.puts [row[0], row[0] - first_row[0], row[1], row[1] - last_row[1]].join(' ')
|
83
|
+
last_row = row
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def escape(value)
|
88
|
+
value.gsub('_', '\\\\_')
|
89
|
+
end
|
90
|
+
|
91
|
+
def plot(output)
|
92
|
+
Dir.mktmpdir do |dir|
|
93
|
+
write_results_for('ips', dir)
|
94
|
+
write_results_for('gc', dir)
|
95
|
+
write_results_for('rss', dir)
|
96
|
+
|
97
|
+
template = File.read(File.expand_path('../templates/gnuplot.sh.erb', __FILE__))
|
98
|
+
_script = ''
|
99
|
+
data_dir = dir
|
100
|
+
ERB.new(template, nil, nil, "_script").result(binding)
|
101
|
+
`gnuplot <<-GNUPLOT\n#{_script}\nGNUPLOT`
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
# ttfb
|
106
|
+
# ttlb
|
107
|
+
end
|
data/lib/analyzer/rss.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'bigdecimal'
|
2
|
+
|
3
|
+
class Analyzer
|
4
|
+
class Rss
|
5
|
+
|
6
|
+
KB_TO_BYTE = 1024 # 2**10 = 1024
|
7
|
+
MB_TO_BYTE = 1_048_576 # 1024**2 = 1_048_576
|
8
|
+
GB_TO_BYTE = 1_073_741_824 # 1024**3 = 1_073_741_824
|
9
|
+
CONVERSION = { "kb" => KB_TO_BYTE, "mb" => MB_TO_BYTE, "gb" => GB_TO_BYTE }
|
10
|
+
|
11
|
+
def initialize(pid = Process.pid)
|
12
|
+
@pid = pid
|
13
|
+
@status_file = "/proc/#{@pid}/status"
|
14
|
+
@linux = File.exists?(@status_file)
|
15
|
+
end
|
16
|
+
|
17
|
+
def bytes
|
18
|
+
@linux ? (linux_status_memory || ps_memory) : ps_memory
|
19
|
+
end
|
20
|
+
|
21
|
+
def inspect
|
22
|
+
"#<#{self.class}:0x%08x @bytes=#{bytes}>" % (object_id * 2)
|
23
|
+
end
|
24
|
+
|
25
|
+
# linux stores memory info in a file "/proc/#{@pid}/status"
|
26
|
+
# If it's available it uses less resources than shelling out to ps
|
27
|
+
def linux_status_memory
|
28
|
+
line = File.new(@status_file).each_line.detect { |l| l.start_with?('VmRSS'.freeze) }
|
29
|
+
if line
|
30
|
+
line = line.split(nil)
|
31
|
+
if line.length == 3
|
32
|
+
CONVERSION[line[1].downcase!] * line[2].to_i
|
33
|
+
end
|
34
|
+
end
|
35
|
+
rescue Errno::EACCES, Errno::ENOENT
|
36
|
+
0
|
37
|
+
end
|
38
|
+
|
39
|
+
# Pull memory from `ps` command, takes more resources and can freeze
|
40
|
+
# in low memory situations
|
41
|
+
def ps_memory
|
42
|
+
KB_TO_BYTE * BigDecimal.new(`ps -o rss= -p #{@pid}`)
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
<%= lib %>
|
2
|
+
<%= setup %>
|
3
|
+
|
4
|
+
__analyzer_not_done = true
|
5
|
+
__analyzer_t = Time.now.to_f
|
6
|
+
__analyzer_gc_stat = GC.stat
|
7
|
+
|
8
|
+
STDOUT.write("[[".freeze)
|
9
|
+
STDOUT.write(__analyzer_t.to_s)
|
10
|
+
STDOUT.write(",".freeze)
|
11
|
+
STDOUT.write(__analyzer_gc_stat[:total_allocated_objects].to_s)
|
12
|
+
STDOUT.write(",".freeze)
|
13
|
+
STDOUT.write(__analyzer_gc_stat[:total_freed_objects].to_s)
|
14
|
+
STDOUT.write(",".freeze)
|
15
|
+
STDOUT.write(__analyzer_gc_stat[:minor_gc_count].to_s)
|
16
|
+
STDOUT.write(",".freeze)
|
17
|
+
STDOUT.write(__analyzer_gc_stat[:major_gc_count].to_s)
|
18
|
+
STDOUT.write("]".freeze)
|
19
|
+
|
20
|
+
__analyzer_mt = Thread.new do
|
21
|
+
while __analyzer_not_done do
|
22
|
+
__analyzer_sleep_t = 0.02 - (Time.now.to_f - __analyzer_t)
|
23
|
+
sleep(__analyzer_sleep_t) if __analyzer_sleep_t > 0
|
24
|
+
|
25
|
+
__analyzer_t = Time.now.to_f
|
26
|
+
__analyzer_gc_stat = GC.stat
|
27
|
+
STDOUT.write(",[".freeze)
|
28
|
+
STDOUT.write(__analyzer_t.to_s)
|
29
|
+
STDOUT.write(",".freeze)
|
30
|
+
STDOUT.write(__analyzer_gc_stat[:total_allocated_objects].to_s)
|
31
|
+
STDOUT.write(",".freeze)
|
32
|
+
STDOUT.write(__analyzer_gc_stat[:total_freed_objects].to_s)
|
33
|
+
STDOUT.write(",".freeze)
|
34
|
+
STDOUT.write(__analyzer_gc_stat[:minor_gc_count].to_s)
|
35
|
+
STDOUT.write(",".freeze)
|
36
|
+
STDOUT.write(__analyzer_gc_stat[:major_gc_count].to_s)
|
37
|
+
STDOUT.write("]".freeze)
|
38
|
+
end
|
39
|
+
|
40
|
+
__analyzer_t = Time.now.to_f
|
41
|
+
__analyzer_gc_stat = GC.stat
|
42
|
+
STDOUT.write(",[".freeze)
|
43
|
+
STDOUT.write(__analyzer_t.to_s)
|
44
|
+
STDOUT.write(",".freeze)
|
45
|
+
STDOUT.write(__analyzer_gc_stat[:total_allocated_objects].to_s)
|
46
|
+
STDOUT.write(",".freeze)
|
47
|
+
STDOUT.write(__analyzer_gc_stat[:total_freed_objects].to_s)
|
48
|
+
STDOUT.write(",".freeze)
|
49
|
+
STDOUT.write(__analyzer_gc_stat[:minor_gc_count].to_s)
|
50
|
+
STDOUT.write(",".freeze)
|
51
|
+
STDOUT.write(__analyzer_gc_stat[:major_gc_count].to_s)
|
52
|
+
STDOUT.write("]]".freeze)
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
__analyzer_start = Time.now.to_f
|
57
|
+
while Time.now.to_f - __analyzer_start < 5
|
58
|
+
<%= src %>
|
59
|
+
end
|
60
|
+
__analyzer_not_done = false
|
61
|
+
__analyzer_mt.join
|
@@ -0,0 +1,76 @@
|
|
1
|
+
reset
|
2
|
+
set terminal pngcairo enhanced font "arial,12" fontscale 1.0 size 900, 1300
|
3
|
+
set output '<%= output %>'
|
4
|
+
|
5
|
+
# define axis
|
6
|
+
# remove border on top and right and set color to gray
|
7
|
+
set style line 11 lc rgb '#808080' lt 1
|
8
|
+
set border 3 back ls 11
|
9
|
+
set tics nomirror
|
10
|
+
# define grid
|
11
|
+
set style line 12 lc rgb '#808080' lt 0 lw 1
|
12
|
+
set grid back ls 12
|
13
|
+
|
14
|
+
set key center bottom horizontal
|
15
|
+
|
16
|
+
set style line 1 linetype 1 linecolor rgb '#5e64ff' pointtype 1 pointsize 1 linewidth 1 # blue
|
17
|
+
set style line 2 linetype 1 linecolor rgb '#ffa00a' pointtype 1 pointsize 1 linewidth 1 # orange
|
18
|
+
set style line 3 linetype 1 linecolor rgb '#28a745' pointtype 1 pointsize 1 linewidth 1 # green
|
19
|
+
set style line 4 linetype 1 linecolor rgb '#b554ff' pointtype 1 pointsize 1 linewidth 1 # purple
|
20
|
+
set style line 5 linetype 1 linecolor rgb '#ff5858' pointtype 1 pointsize 1 linewidth 1 # red
|
21
|
+
set style line 6 linetype 1 linecolor rgb '#FEEF72' pointtype 1 pointsize 1 linewidth 1 # yellow
|
22
|
+
set style line 7 linetype 1 linecolor rgb '#7CD6FD' pointtype 1 pointsize 1 linewidth 1 # light-blue
|
23
|
+
set style line 8 linetype 1 linecolor rgb '#8b1a0e' pointtype 1 pointsize 1 linewidth 1 # dark-red
|
24
|
+
|
25
|
+
|
26
|
+
set multiplot layout 5, 1
|
27
|
+
set tmargin 4
|
28
|
+
set bmargin 4
|
29
|
+
|
30
|
+
set title "Iterations / Sec" font ",14"
|
31
|
+
set key off
|
32
|
+
set format y '%.1s %c'
|
33
|
+
|
34
|
+
|
35
|
+
|
36
|
+
set boxwidth 0.15 absolute
|
37
|
+
|
38
|
+
set style data boxplot
|
39
|
+
set style boxplot range 2 nooutliers candlesticks
|
40
|
+
set style fill solid 0.2
|
41
|
+
set xtics (<%= tests.map.with_index { |f, i| "'#{escape(f)}' #{i+1}"}.join(', ') %>) scale 0,0
|
42
|
+
|
43
|
+
plot <%= tests.map.with_index { |t, i| "'#{File.join(data_dir, 'ips', t)}' using (#{i+1}.0):1 with boxplot linestyle #{i+1}" }.join(', ') %>
|
44
|
+
|
45
|
+
|
46
|
+
set title "GC Objects Allocated"
|
47
|
+
set key on
|
48
|
+
set yrange [0:*]
|
49
|
+
set xrange [0:5]
|
50
|
+
set xtics autofreq
|
51
|
+
|
52
|
+
|
53
|
+
plot <%= tests.map.with_index { |k, i| "'#{File.join(data_dir, 'gc', k)}' using 2:5 title '#{escape(k)}' with steps linestyle #{i+1}" }.join(', ') %>
|
54
|
+
|
55
|
+
set title "GC Objects Freed"
|
56
|
+
set key on
|
57
|
+
set yrange [0:*]
|
58
|
+
set xrange [0:5]
|
59
|
+
|
60
|
+
plot <%= tests.map.with_index { |k, i| "'#{File.join(data_dir, 'gc', k)}' using 2:6 title '#{escape(k)}' with steps linestyle #{i+1}" }.join(', ') %>
|
61
|
+
|
62
|
+
set title "GC Retained"
|
63
|
+
set key on
|
64
|
+
set yrange [0:*]
|
65
|
+
set xrange [0:5]
|
66
|
+
|
67
|
+
plot <%= tests.map.with_index { |k, i| "'#{File.join(data_dir, 'gc', k)}' using 2:(\\$3-\\$4) title '#{escape(k)}' with steps linestyle #{i+1}" }.join(', ') %>
|
68
|
+
|
69
|
+
# , \\$alloc#{k} using 1:8 with impulses linestyle 7 title 'minor' axes x1y2, \\$alloc#{k} using 1:9 with impulses linestyle 8 title 'major' axes x1y2
|
70
|
+
|
71
|
+
set title "RSS"
|
72
|
+
set key on
|
73
|
+
set yrange [0:*]
|
74
|
+
set xrange [0:5]
|
75
|
+
|
76
|
+
plot <%= tests.map.with_index { |k, i| "'#{File.join(data_dir, 'rss', k)}' using 2:3 title '#{escape(k)}' with steps linestyle #{i+1}" }.join(', ') %>
|
@@ -0,0 +1,23 @@
|
|
1
|
+
<%= lib %>
|
2
|
+
<%= setup %>
|
3
|
+
|
4
|
+
require 'benchmark/ips'
|
5
|
+
|
6
|
+
class Benchmark::IPS::Job
|
7
|
+
def create_stats(samples)
|
8
|
+
samples
|
9
|
+
end
|
10
|
+
|
11
|
+
def create_report(label, measured_us, iter, samples, cycles)
|
12
|
+
require 'json'
|
13
|
+
STDOUT.puts JSON.generate(samples)
|
14
|
+
@full_report.add_entry label, measured_us, iter, Benchmark::IPS::Stats::SD.new(samples), cycles
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
Benchmark.ips(quiet: true) do |x|
|
19
|
+
x.config(stats: :bootstrap, confidence: 98)
|
20
|
+
x.report("analyze", <<-CODEFILE)
|
21
|
+
<%= src %>
|
22
|
+
CODEFILE
|
23
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
<%= lib %>
|
2
|
+
<%= setup %>
|
3
|
+
|
4
|
+
__analyzer_read, __analyzer_write = IO.pipe
|
5
|
+
if child_pid = fork
|
6
|
+
__analyzer_read.close
|
7
|
+
require '<%= File.join(analyzer_dir, 'analyzer/rss') %>'
|
8
|
+
|
9
|
+
not_done = true
|
10
|
+
bytes = 0
|
11
|
+
monitor = Analyzer::Rss.new(child_pid)
|
12
|
+
|
13
|
+
|
14
|
+
|
15
|
+
time = Time.now.to_f
|
16
|
+
bytes = monitor.bytes
|
17
|
+
|
18
|
+
STDOUT.write("[[".freeze)
|
19
|
+
STDOUT.write(time.to_s)
|
20
|
+
STDOUT.write(",".freeze)
|
21
|
+
STDOUT.write(bytes.to_s)
|
22
|
+
STDOUT.write("]".freeze)
|
23
|
+
|
24
|
+
__analyzer_write.puts "go".freeze
|
25
|
+
__analyzer_write.close
|
26
|
+
while bytes != 0 do
|
27
|
+
sleep_time = 0.02 - (Time.now.to_f - time)
|
28
|
+
sleep(sleep_time) if sleep_time > 0
|
29
|
+
|
30
|
+
time = Time.now.to_f
|
31
|
+
bytes = monitor.bytes
|
32
|
+
STDOUT.write(",[".freeze)
|
33
|
+
STDOUT.write(time.to_s)
|
34
|
+
STDOUT.write(",".freeze)
|
35
|
+
STDOUT.write(bytes.to_s)
|
36
|
+
STDOUT.write("]".freeze)
|
37
|
+
end
|
38
|
+
|
39
|
+
STDOUT.write("]".freeze)
|
40
|
+
else
|
41
|
+
__analyzer_write.close
|
42
|
+
raise 'fail' if __analyzer_read.gets != "go\n".freeze
|
43
|
+
__analyzer_read.close
|
44
|
+
|
45
|
+
__analyzer_start = Time.now.to_f
|
46
|
+
while Time.now.to_f - __analyzer_start < 5
|
47
|
+
<%= src %>
|
48
|
+
end
|
49
|
+
end
|
metadata
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: analyzer
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jon Bracy
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-11-13 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: benchmark-ips
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '2.7'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '2.7'
|
27
|
+
description:
|
28
|
+
email:
|
29
|
+
- jonbracy@gmail.com
|
30
|
+
executables:
|
31
|
+
- analyze
|
32
|
+
extensions: []
|
33
|
+
extra_rdoc_files: []
|
34
|
+
files:
|
35
|
+
- LICENSE
|
36
|
+
- README.md
|
37
|
+
- analyzer.gemspec
|
38
|
+
- bin/analyze
|
39
|
+
- example_report.png
|
40
|
+
- lib/analyzer.rb
|
41
|
+
- lib/analyzer/rss.rb
|
42
|
+
- lib/analyzer/version.rb
|
43
|
+
- lib/templates/gc.rb.erb
|
44
|
+
- lib/templates/gnuplot.sh.erb
|
45
|
+
- lib/templates/ips.rb.erb
|
46
|
+
- lib/templates/rss.rb.erb
|
47
|
+
homepage: https://github.com/malomalo/analyzer
|
48
|
+
licenses:
|
49
|
+
- MIT
|
50
|
+
metadata:
|
51
|
+
source_code_uri: https://github.com/malomalo/analyzer
|
52
|
+
post_install_message:
|
53
|
+
rdoc_options: []
|
54
|
+
require_paths:
|
55
|
+
- lib
|
56
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '2'
|
61
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
62
|
+
requirements:
|
63
|
+
- - ">="
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
requirements:
|
67
|
+
- gnuplot
|
68
|
+
rubyforge_project:
|
69
|
+
rubygems_version: 2.6.11
|
70
|
+
signing_key:
|
71
|
+
specification_version: 4
|
72
|
+
summary: A Performance analyzer for Ruby
|
73
|
+
test_files: []
|