perf_check 0.1.6 → 0.1.7
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/bin/perf_check +46 -4
- data/lib/perf_check/git.rb +0 -1
- data/lib/perf_check/railtie.rb +4 -0
- data/lib/perf_check/server.rb +46 -3
- data/lib/perf_check/test_case.rb +65 -23
- data/lib/perf_check.rb +51 -7
- metadata +15 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 55dd84ea36a6406e768ed5581acf65b9f4b6aa50
|
4
|
+
data.tar.gz: fb5b16a1aea5f51c75af09c9843d4bd3a063ff30
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1377387b9ef80a3bbbc9128b4461bf89ffb189fcbee5f2f685becee729681affb51a193725a5bcc414f0ac9eb57176c010fb89bd4a1a403ee8194f33aadbabc0
|
7
|
+
data.tar.gz: 64d8c600ad45a422698f31717e0612a150f7899d7252cf60c4c9c9fb70f531e13445605a9783c126dcaa1c30b06d9c5706ccf19bab9651c1e612aa24b7f78ba5
|
data/bin/perf_check
CHANGED
@@ -8,7 +8,8 @@ options.login = nil
|
|
8
8
|
options.number_of_requests = 10
|
9
9
|
options.reference = 'master'
|
10
10
|
options.http_statuses = [200]
|
11
|
-
|
11
|
+
options.verify_responses = false
|
12
|
+
options.caching = true
|
12
13
|
|
13
14
|
opts = OptionParser.new do |opts|
|
14
15
|
opts.banner = "Usage: perf_check [options] [route ...]"
|
@@ -52,7 +53,11 @@ opts = OptionParser.new do |opts|
|
|
52
53
|
end
|
53
54
|
|
54
55
|
opts.on('--no-caching', 'Do not enable fragment caching') do
|
55
|
-
|
56
|
+
options.caching = false
|
57
|
+
end
|
58
|
+
|
59
|
+
opts.on('--fail-fast', '-f', 'Bail immediately on non-200 HTTP response') do
|
60
|
+
options[:fail_fast?] = true
|
56
61
|
end
|
57
62
|
|
58
63
|
opts.on('--302-success', 'Consider HTTP 302 code a successful request') do
|
@@ -63,6 +68,29 @@ opts = OptionParser.new do |opts|
|
|
63
68
|
options.http_statuses.delete(302)
|
64
69
|
end
|
65
70
|
|
71
|
+
opts.separator "\nMisc"
|
72
|
+
opts.on('--input FILE', '-i') do |input|
|
73
|
+
File.readlines(input).each do |resource|
|
74
|
+
ARGV << resource.strip
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
opts.on('--verify-responses',
|
79
|
+
'Check whether there is a diff between the responses of this and the reference branch') do
|
80
|
+
options.verify_responses = true
|
81
|
+
end
|
82
|
+
|
83
|
+
opts.on('--brief', '-b') do
|
84
|
+
options.brief = true
|
85
|
+
end
|
86
|
+
|
87
|
+
opts.on('--diff') do
|
88
|
+
options.diff = true
|
89
|
+
options.brief = true
|
90
|
+
options.verify_responses = true
|
91
|
+
options.number_of_requests = 1
|
92
|
+
end
|
93
|
+
|
66
94
|
opts.separator ''
|
67
95
|
opts.separator <<EOF
|
68
96
|
Usage examples:
|
@@ -70,6 +98,7 @@ Usage examples:
|
|
70
98
|
perf_check /user/45/posts
|
71
99
|
perf_check /user/45/posts -n5
|
72
100
|
perf_check /user/45/posts --standard
|
101
|
+
perf_check /user/45/posts --admin
|
73
102
|
|
74
103
|
Benchmark against a specific commit
|
75
104
|
perf_check /user/45/posts -r 0123abcdefg
|
@@ -77,11 +106,20 @@ Usage examples:
|
|
77
106
|
|
78
107
|
Benchmark the changes in the working tree
|
79
108
|
perf_check /user/45/posts -r HEAD
|
109
|
+
|
110
|
+
Benchmark and diff the output against master
|
111
|
+
perf_check /user/45/posts --verify-responses
|
112
|
+
|
113
|
+
Just diff the output on your branch with master
|
114
|
+
perf_check /user/45/posts --diff
|
115
|
+
|
116
|
+
Diff a bunch of urls listed in a file (newline seperated)
|
117
|
+
perf_check --diff --input FILE
|
80
118
|
EOF
|
81
119
|
end
|
82
120
|
opts.parse!
|
83
121
|
|
84
|
-
PerfCheck.require_rails
|
122
|
+
PerfCheck.require_rails(options)
|
85
123
|
|
86
124
|
ARGV.each do |route|
|
87
125
|
perf_check.add_test_case(route)
|
@@ -94,7 +132,11 @@ end
|
|
94
132
|
perf_check.sanity_check
|
95
133
|
perf_check.run
|
96
134
|
|
97
|
-
|
135
|
+
if options.brief
|
136
|
+
perf_check.print_brief_results
|
137
|
+
else
|
138
|
+
perf_check.print_results
|
139
|
+
end
|
98
140
|
|
99
141
|
# _______________________
|
100
142
|
# < You made it faster!!! >
|
data/lib/perf_check/git.rb
CHANGED
data/lib/perf_check/railtie.rb
CHANGED
@@ -21,6 +21,10 @@ class PerfCheck
|
|
21
21
|
config = ActiveSupport::Configurable::Configuration
|
22
22
|
config.send(:define_method, :perform_caching){ fragment_caching }
|
23
23
|
end
|
24
|
+
|
25
|
+
if ENV['PERF_CHECK'] && ENV['PERF_CHECK_VERIFICATION']
|
26
|
+
PerfCheck::Server.seed_random!
|
27
|
+
end
|
24
28
|
end
|
25
29
|
end
|
26
30
|
end
|
data/lib/perf_check/server.rb
CHANGED
@@ -12,7 +12,7 @@ class PerfCheck
|
|
12
12
|
|
13
13
|
def self.authorization_action(method, login_route, &block)
|
14
14
|
Rails.application.reload_routes!
|
15
|
-
p =
|
15
|
+
p = PerfCheck::Server.recognize_path(login_route, :method => method)
|
16
16
|
controller = "#{p[:controller]}_controller".classify.constantize
|
17
17
|
action = p[:action]
|
18
18
|
|
@@ -35,6 +35,49 @@ class PerfCheck
|
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
|
+
def self.mounted_path(engine)
|
39
|
+
route = Rails.application.routes.routes.detect do |route|
|
40
|
+
route.app == engine
|
41
|
+
end
|
42
|
+
route && route.path
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.recognize_path(path, opts={})
|
46
|
+
Rails::Engine.subclasses.each do |engine|
|
47
|
+
if match = mounted_path(engine) =~ path
|
48
|
+
path = path.sub(match.to_s, '')
|
49
|
+
return engine.routes.recognize_path(path, opts)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
Rails.application.routes.recognize_path(path, opts)
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.seed_random!
|
56
|
+
# Seed random
|
57
|
+
srand(1)
|
58
|
+
|
59
|
+
# SecureRandom cannot be seeded, so we have to monkey patch it instead :\
|
60
|
+
def SecureRandom.hex(n=16)
|
61
|
+
'4' * n
|
62
|
+
end
|
63
|
+
|
64
|
+
def SecureRandom.random_bytes(n=16)
|
65
|
+
'4' * n
|
66
|
+
end
|
67
|
+
|
68
|
+
def SecureRandom.random_number(n=0)
|
69
|
+
n > 4 ? 4 : n
|
70
|
+
end
|
71
|
+
|
72
|
+
def SecureRandom.urlsafe_base64(n=16, padding=false)
|
73
|
+
'4' * (4*n / 3)
|
74
|
+
end
|
75
|
+
|
76
|
+
def SecureRandom.uuid
|
77
|
+
"00000000-0000-0000-0000-000000000004"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
38
81
|
def self.sign_cookie_data(key, data, opts={})
|
39
82
|
opts[:serializer] ||= Marshal
|
40
83
|
secret = Rails.application.config.secret_token
|
@@ -116,10 +159,10 @@ class PerfCheck
|
|
116
159
|
|
117
160
|
def restart
|
118
161
|
if !@running
|
119
|
-
$stderr.print "starting rails
|
162
|
+
$stderr.print "starting rails...\n"
|
120
163
|
start
|
121
164
|
else
|
122
|
-
$stderr.print "re-starting rails
|
165
|
+
$stderr.print "re-starting rails...\n"
|
123
166
|
exit
|
124
167
|
start
|
125
168
|
end
|
data/lib/perf_check/test_case.rb
CHANGED
@@ -1,17 +1,18 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
|
3
|
+
require 'diffy'
|
4
|
+
|
3
5
|
class PerfCheck
|
4
6
|
class TestCase
|
5
7
|
attr_accessor :resource, :controller, :action, :format
|
6
|
-
attr_accessor :
|
7
|
-
attr_accessor :
|
8
|
+
attr_accessor :cookie, :this_response, :reference_response
|
9
|
+
attr_accessor :this_profiles, :reference_profiles
|
8
10
|
|
9
11
|
def initialize(route)
|
10
|
-
params =
|
12
|
+
params = PerfCheck::Server.recognize_path(route)
|
11
13
|
|
12
|
-
self.
|
13
|
-
self.
|
14
|
-
self.latencies = this_latencies
|
14
|
+
self.this_profiles = []
|
15
|
+
self.reference_profiles = []
|
15
16
|
|
16
17
|
self.controller = params[:controller].split('/')[-1]
|
17
18
|
self.action = params[:action]
|
@@ -19,11 +20,20 @@ class PerfCheck
|
|
19
20
|
self.resource = route
|
20
21
|
end
|
21
22
|
|
23
|
+
def switch_to_reference_context
|
24
|
+
@context = :reference
|
25
|
+
end
|
26
|
+
|
22
27
|
def run(server, options)
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
28
|
+
unless options.diff
|
29
|
+
print("\t"+'request #'.underline)
|
30
|
+
print(" "+'latency'.underline)
|
31
|
+
print(" "+'server rss'.underline)
|
32
|
+
print(" "+'status'.underline)
|
33
|
+
puts(" "+'profiler data'.underline)
|
34
|
+
end
|
35
|
+
|
36
|
+
profiles = (@context == :reference) ? reference_profiles : this_profiles
|
27
37
|
|
28
38
|
headers = {'Cookie' => "#{cookie}"}
|
29
39
|
unless self.format
|
@@ -35,31 +45,47 @@ class PerfCheck
|
|
35
45
|
end
|
36
46
|
|
37
47
|
unless options.http_statuses.include? profile.response_code
|
38
|
-
|
39
|
-
|
48
|
+
if options.fail_fast?
|
49
|
+
File.open("tmp/perf_check/failed_request.html", 'w') do |error_dump|
|
50
|
+
error_dump.write(profile.response_body)
|
51
|
+
end
|
52
|
+
error = sprintf("\t%2i:\tFAILED! (HTTP %d)", i, profile.response_code)
|
53
|
+
puts(error.red.bold)
|
54
|
+
puts("\t The server responded with a non-2xx status for this request.")
|
55
|
+
puts("\t The response has been written to tmp/perf_check/failed_request.html")
|
56
|
+
exit(1)
|
40
57
|
end
|
41
|
-
error = sprintf("\t%2i:\tFAILED! (HTTP %d)", i, profile.response_code)
|
42
|
-
puts(error.red.bold)
|
43
|
-
puts("\t The server responded with a non-2xx status for this request.")
|
44
|
-
puts("\t The response has been written to tmp/perf_check/failed_request.html")
|
45
|
-
exit(1)
|
46
58
|
end
|
47
59
|
|
48
60
|
next if i.zero?
|
49
|
-
printf("\t%2i:\t %.1fms %4dMB\t %s\n",
|
50
|
-
i, profile.latency, server.mem, profile.profile_url)
|
51
61
|
|
52
|
-
|
62
|
+
if options.verify_responses
|
63
|
+
if i == 1
|
64
|
+
if @context == :reference
|
65
|
+
self.reference_response = profile.response_body
|
66
|
+
else
|
67
|
+
self.this_response = profile.response_body
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
unless options.diff
|
73
|
+
printf("\t%2i:\t %.1fms %4dMB\t %s\t %s\n",
|
74
|
+
i, profile.latency, server.mem,
|
75
|
+
profile.response_code, profile.profile_url)
|
76
|
+
end
|
77
|
+
|
78
|
+
profiles << profile
|
53
79
|
end
|
54
|
-
puts
|
80
|
+
puts unless options.diff # pretty!
|
55
81
|
end
|
56
82
|
|
57
83
|
def this_latency
|
58
|
-
|
84
|
+
this_profiles.map(&:latency).inject(0.0, :+) / this_profiles.size
|
59
85
|
end
|
60
86
|
|
61
87
|
def reference_latency
|
62
|
-
|
88
|
+
reference_profiles.map(&:latency).inject(0.0, :+) / reference_profiles.size
|
63
89
|
end
|
64
90
|
|
65
91
|
def latency_difference
|
@@ -70,6 +96,22 @@ class PerfCheck
|
|
70
96
|
reference_latency / this_latency
|
71
97
|
end
|
72
98
|
|
99
|
+
def response_diff
|
100
|
+
diff = Diffy::Diff.new(this_response, reference_response,
|
101
|
+
:diff => PerfCheck.diff_options)
|
102
|
+
if diff.to_s.empty?
|
103
|
+
OpenStruct.new(:changed? => false)
|
104
|
+
else
|
105
|
+
FileUtils.mkdir_p("#{Rails.root}/tmp/perf_check/diffs")
|
106
|
+
file = `mktemp -u "#{Rails.root}/tmp/perf_check/diffs/XXXXXXXXXX"`.strip
|
107
|
+
[:text, :html].each do |format|
|
108
|
+
ext = {:text => 'diff', :html => 'html'}[format]
|
109
|
+
File.open("#{file}.#{ext}", 'w'){ |f| f.write(diff.to_s(format)) }
|
110
|
+
end
|
111
|
+
OpenStruct.new(:changed? => true, :file => "#{file}.diff")
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
73
115
|
def eql?(test)
|
74
116
|
resource == test.resource
|
75
117
|
end
|
data/lib/perf_check.rb
CHANGED
@@ -11,8 +11,19 @@ require 'colorize'
|
|
11
11
|
class PerfCheck
|
12
12
|
attr_accessor :options, :server, :test_cases
|
13
13
|
|
14
|
-
def self.
|
14
|
+
def self.diff_options
|
15
|
+
@@diff_options ||=
|
16
|
+
['-U3', '--ignore-matching-lines=/mini-profiler-resources/includes.js']
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.require_rails(options)
|
15
20
|
ENV['PERF_CHECK'] = '1'
|
21
|
+
if options.verify_responses
|
22
|
+
ENV['PERF_CHECK_VERIFICATION'] = '1'
|
23
|
+
end
|
24
|
+
if !options.caching
|
25
|
+
ENV['PERF_CHECK_NOCACHING'] = '1'
|
26
|
+
end
|
16
27
|
|
17
28
|
app_root = Dir.pwd
|
18
29
|
until app_root == '/' || File.exist?("#{app_root}/config/application.rb")
|
@@ -57,28 +68,59 @@ class PerfCheck
|
|
57
68
|
if i == 1
|
58
69
|
Git.stash_if_needed
|
59
70
|
Git.checkout_reference(options.reference)
|
60
|
-
test_cases.each{ |x| x.
|
71
|
+
test_cases.each{ |x| x.switch_to_reference_context }
|
61
72
|
end
|
62
73
|
|
63
|
-
|
64
|
-
|
74
|
+
server.restart
|
75
|
+
test_cases.each_with_index do |test, i|
|
76
|
+
server.restart unless i.zero? || options.diff
|
65
77
|
|
66
78
|
if options.login
|
67
79
|
test.cookie = server.login(options.login, test)
|
68
80
|
end
|
69
81
|
|
70
|
-
|
82
|
+
if options.diff
|
83
|
+
puts "Issuing #{test.resource}"
|
84
|
+
else
|
85
|
+
puts("\nBenchmarking #{test.resource}:")
|
86
|
+
end
|
71
87
|
test.run(server, options)
|
72
88
|
end
|
73
89
|
end
|
74
90
|
end
|
75
91
|
|
92
|
+
|
93
|
+
def print_diff_results(diff)
|
94
|
+
if diff.changed?
|
95
|
+
print(" Diff: #{diff.file}".bold.light_red)
|
96
|
+
else
|
97
|
+
print(" Diff: Output is identical!".bold.light_green)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def print_brief_results
|
102
|
+
test_cases.each do |test|
|
103
|
+
print(test.resource.ljust(40) + ': ')
|
104
|
+
|
105
|
+
codes = (test.this_profiles+test.reference_profiles).map(&:response_code).uniq
|
106
|
+
print("(HTTP "+codes.join(',')+") ")
|
107
|
+
|
108
|
+
printf('%.1fms', test.this_latency)
|
109
|
+
|
110
|
+
puts && next if test.reference_profiles.empty?
|
111
|
+
|
112
|
+
print(sprintf(' (%+5.1fms)', test.latency_difference).bold)
|
113
|
+
print_diff_results(test.response_diff) if options.verify_responses
|
114
|
+
puts
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
76
118
|
def print_results
|
77
119
|
puts("==== Results ====")
|
78
120
|
test_cases.each do |test|
|
79
|
-
puts(test.resource)
|
121
|
+
puts(test.resource.bold)
|
80
122
|
|
81
|
-
if test.
|
123
|
+
if test.reference_profiles.empty?
|
82
124
|
printf("your branch: ".rjust(15)+"%.1fms\n", test.this_latency)
|
83
125
|
next
|
84
126
|
end
|
@@ -110,6 +152,8 @@ class PerfCheck
|
|
110
152
|
puts("master: ".rjust(15) + "#{master_latency}")
|
111
153
|
puts("your branch: ".rjust(15)+ "#{this_latency}")
|
112
154
|
puts(("change: ".rjust(15) + "#{formatted_change}").bold.send(color))
|
155
|
+
|
156
|
+
print_diff_results(test.response_diff) if options.verify_responses
|
113
157
|
end
|
114
158
|
end
|
115
159
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: perf_check
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- rubytune
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - '='
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 0.7.3
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: diffy
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 3.0.5
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 3.0.5
|
27
41
|
description:
|
28
42
|
email:
|
29
43
|
executables:
|