Class: PerfCheck
- Defined in:
- lib/perf_check.rb,
lib/perf_check/git.rb,
lib/perf_check/config.rb,
lib/perf_check/logger.rb,
lib/perf_check/output.rb,
lib/perf_check/server.rb,
lib/perf_check/railtie.rb,
lib/perf_check/callbacks.rb,
lib/perf_check/test_case.rb,
lib/perf_check/middleware.rb
Defined Under Namespace
Classes: Git, Middleware, Railtie, Server, TestCase
Constant Summary collapse
- Options =
OptionParser.new do |opts| opts. = "Usage: perf_check [options] [route ...]" opts.separator "\nBenchmark options:" opts.on('--requests N', '-n', 'Use N requests in benchmark, defaults to 10') do |n| config.number_of_requests = n.to_i end opts.on('--reference COMMIT', '-r', 'Benchmark against COMMIT instead of master') do |commit| config.reference = commit end opts.on('--quick', '-q', 'Fire off 5 requests just on this branch, no comparison with master') do config.number_of_requests = 5 config.reference = nil end opts.on('--no-caching', 'Do not enable fragment caching') do config.caching = false end opts.on('--fail-fast', '-f', 'Bail immediately on non-200 HTTP response') do config[:fail_fast?] = true end opts.on('--302-success', 'Consider HTTP 302 code a successful request') do config.http_statuses.push(302) end opts.on('--302-failure', 'Consider HTTP 302 code an unsuccessful request') do config.http_statuses.delete(302) end opts.separator "\nMisc" opts.on('--cookie COOKIE', '-c') do || config. = end opts.on('--json', '-j') do config.json = true end opts.on('--input FILE', '-i') do |input| File.readlines(input).each do |resource| ARGV << resource.strip end end opts.on('--verify-responses', 'Check whether there is a diff between the responses of this and the reference branch') do config.verify_responses = true end opts.on('--brief', '-b') do config.brief = true end opts.on('--diff') do config.diff = true config.brief = true config.verify_responses = true config.number_of_requests = 1 end opts.separator '' opts.separator "Usage examples:\nBenchmark PostController#index against master\n perf_check /user/45/posts\n perf_check /user/45/posts -n5\n\nBenchmark against a specific commit\n perf_check /user/45/posts -r 0123abcdefg\n perf_check /user/45/posts -r HEAD~2\n\nBenchmark the changes in the working tree\n perf_check /user/45/posts -r HEAD\n\nBenchmark and diff the output against master\n perf_check /user/45/posts --verify-responses\n\nJust diff the output on your branch with master\n perf_check /user/45/posts --diff\n\nDiff a bunch of urls listed in a file (newline seperated)\n perf_check --diff --input FILE\n" opts.separator '' end
Instance Attribute Summary collapse
-
#options ⇒ Object
Sets the attribute options.
-
#server ⇒ Object
Returns the value of attribute server.
-
#test_cases ⇒ Object
Returns the value of attribute test_cases.
Class Method Summary collapse
- .app_root ⇒ Object
- .before_start(&block) ⇒ Object
- .before_start_callbacks ⇒ Object
- .config ⇒ Object
- .diff_options ⇒ Object
- .load_config ⇒ Object
- .logger ⇒ Object
- .when_finished(&block) ⇒ Object
- .when_finished_callbacks ⇒ Object
Instance Method Summary collapse
- #add_test_case(route) ⇒ Object
- #config ⇒ Object (also: #options)
-
#initialize ⇒ PerfCheck
constructor
A new instance of PerfCheck.
- #logger ⇒ Object
- #print_brief_results ⇒ Object
- #print_diff_results(diff) ⇒ Object
- #print_full_results ⇒ Object
- #print_json_results ⇒ Object
- #run ⇒ Object
- #trigger_before_start_callbacks ⇒ Object
- #trigger_when_finished_callbacks(data = {}) ⇒ Object
Constructor Details
#initialize ⇒ PerfCheck
Returns a new instance of PerfCheck.
27 28 29 30 31 |
# File 'lib/perf_check.rb', line 27 def initialize self. = OpenStruct.new self.server = Server.new self.test_cases = [] end |
Instance Attribute Details
#options=(value) ⇒ Object
Sets the attribute options
10 11 12 |
# File 'lib/perf_check.rb', line 10 def (value) = value end |
#server ⇒ Object
Returns the value of attribute server.
10 11 12 |
# File 'lib/perf_check.rb', line 10 def server @server end |
#test_cases ⇒ Object
Returns the value of attribute test_cases.
10 11 12 |
# File 'lib/perf_check.rb', line 10 def test_cases @test_cases end |
Class Method Details
.app_root ⇒ Object
12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
# File 'lib/perf_check.rb', line 12 def self.app_root @app_root ||= begin dir = Dir.pwd until dir == '/' || File.exist?("#{dir}/config/application.rb") dir = File.dirname(dir) end unless File.exist?("#{dir}/config/application.rb") abort("perf_check should be run from a rails directory") end dir end end |
.before_start(&block) ⇒ Object
12 13 14 15 |
# File 'lib/perf_check/callbacks.rb', line 12 def self.before_start(&block) @before_start_callbacks ||= [] @before_start_callbacks << block end |
.before_start_callbacks ⇒ Object
17 18 19 20 21 22 23 24 25 |
# File 'lib/perf_check/callbacks.rb', line 17 def self.before_start_callbacks (@before_start_callbacks || []) + [ proc { logger.info("=" * 77) logger.info("PERRRRF CHERRRK! Grab a ☕️ and don't touch your working tree (we automate git)") logger.info("=" * 77) } ] end |
.config ⇒ Object
4 5 6 7 8 9 10 11 12 13 14 |
# File 'lib/perf_check/config.rb', line 4 def self.config @config ||= OpenStruct.new( number_of_requests: 10, reference: 'master', cookie: nil, http_statuses: [200], verify_responses: false, caching: true, json: false ) end |
.diff_options ⇒ Object
116 117 118 119 |
# File 'lib/perf_check/config.rb', line 116 def self. ||= ['-U3', '--ignore-matching-lines=/mini-profiler-resources/includes.js'] end |
.load_config ⇒ Object
121 122 123 124 125 |
# File 'lib/perf_check/config.rb', line 121 def self.load_config if File.exists?("#{app_root}/config/perf_check.rb") require "#{app_root}/config/perf_check" end end |
.logger ⇒ Object
5 6 7 8 9 10 11 |
# File 'lib/perf_check/logger.rb', line 5 def self.logger @logger ||= Logger.new(STDERR).tap do |logger| logger.formatter = proc do |severity, datetime, progname, msg| "[#{datetime}] #{sprintf('%5s', severity)} --: #{msg}\n" end end end |
.when_finished(&block) ⇒ Object
3 4 5 6 |
# File 'lib/perf_check/callbacks.rb', line 3 def self.when_finished(&block) @when_finished_callbacks ||= [] @when_finished_callbacks << block end |
.when_finished_callbacks ⇒ Object
8 9 10 |
# File 'lib/perf_check/callbacks.rb', line 8 def self.when_finished_callbacks @when_finished_callbacks || [] end |
Instance Method Details
#add_test_case(route) ⇒ Object
33 34 35 |
# File 'lib/perf_check.rb', line 33 def add_test_case(route) test_cases.push(TestCase.new(route.sub(/^([^\/])/, '/\1'))) end |
#config ⇒ Object Also known as: options
16 17 18 |
# File 'lib/perf_check/config.rb', line 16 def config PerfCheck.config end |
#logger ⇒ Object
13 |
# File 'lib/perf_check/logger.rb', line 13 def logger; self.class.logger; end |
#print_brief_results ⇒ Object
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
# File 'lib/perf_check/output.rb', line 11 def print_brief_results test_cases.each do |test| print(test.resource.ljust(40) + ': ') codes = (test.this_profiles+test.reference_profiles).map(&:response_code).uniq print("(HTTP "+codes.join(',')+") ") printf('%.1fms', test.this_latency) puts && next if test.reference_profiles.empty? print(sprintf(' (%+5.1fms)', test.latency_difference).bold) print_diff_results(test.response_diff) if .verify_responses puts end end |
#print_diff_results(diff) ⇒ Object
3 4 5 6 7 8 9 |
# File 'lib/perf_check/output.rb', line 3 def print_diff_results(diff) if diff.changed? print(" Diff: #{diff.file}".bold.light_red) else print(" Diff: Output is identical!".bold.light_green) end end |
#print_full_results ⇒ Object
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
# File 'lib/perf_check/output.rb', line 28 def print_full_results puts("==== Results ====") test_cases.each do |test| puts(test.resource.bold) if test.reference_profiles.empty? printf("your branch: ".rjust(15)+"%.1fms\n", test.this_latency) next end master_latency = sprintf('%.1fms', test.reference_latency) this_latency = sprintf('%.1fms', test.this_latency) difference = sprintf('%+.1fms', test.latency_difference) if test.latency_difference < 0 change_factor = test.reference_latency / test.this_latency else change_factor = test.this_latency / test.reference_latency end formatted_change = sprintf('%.1fx', change_factor) percent_change = 100*(test.latency_difference / test.reference_latency).abs if percent_change < 10 formatted_change = "yours is about the same" color = :blue elsif test.latency_difference < 0 formatted_change = "yours is #{formatted_change} faster!" color = :green else formatted_change = "yours is #{formatted_change} slower!!!" color = :light_red end formatted_change = difference + " (#{formatted_change})" puts("reference: ".rjust(15) + "#{master_latency}") puts("your branch: ".rjust(15)+ "#{this_latency}") puts(("change: ".rjust(15) + "#{formatted_change}").bold.send(color)) print_diff_results(test.response_diff) if .verify_responses end end |
#print_json_results ⇒ Object
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
# File 'lib/perf_check/output.rb', line 70 def print_json_results results = [] test_cases.each do |test| results.push( route: test.resource, latency: test.this_latency, query_count: test.this_query_count, requests: [] ) test.this_profiles.each do |profile| results[-1][:requests].push( latency: profile.latency, query_count: profile.query_count, server_memory: profile.server_memory, response_code: profile.response_code, miniprofiler_url: profile.profile_url ) end if .reference results[-1].merge!( reference_latency: test.reference_latency, latency_difference: test.latency_difference, speedup_factor: test.reference_latency / test.this_latency, reference_query_count: test.reference_query_count, reference_requests: [] ) test.reference_profiles.each do |profile| results[-1][:reference_requests].push( latency: profile.latency, query_count: profile.query_count, server_memory: profile.server_memory, response_code: profile.response_code, miniprofiler_url: profile.profile_url ) end end end puts JSON.pretty_generate(results) end |
#run ⇒ Object
37 38 39 40 41 42 43 44 45 46 47 48 49 |
# File 'lib/perf_check.rb', line 37 def run trigger_before_start_callbacks profile_requests if .reference Git.stash_if_needed Git.checkout_reference(.reference) test_cases.each{ |x| x.switch_to_reference_context } profile_requests end end |
#trigger_before_start_callbacks ⇒ Object
28 29 30 |
# File 'lib/perf_check/callbacks.rb', line 28 def trigger_before_start_callbacks PerfCheck.before_start_callbacks.each{ |f| f.call(self) } end |
#trigger_when_finished_callbacks(data = {}) ⇒ Object
32 33 34 35 36 37 38 39 40 41 |
# File 'lib/perf_check/callbacks.rb', line 32 def trigger_when_finished_callbacks(data={}) data = data.merge(:current_branch => PerfCheck::Git.current_branch) results = OpenStruct.new(data) results[:ARGV] = ORIGINAL_ARGV if test_cases.size == 1 results.current_latency = test_cases.first.this_latency results.reference_latency = test_cases.first.reference_latency end PerfCheck.when_finished_callbacks.each{ |f| f.call(results) } end |