@@ -3,79 +3,127 @@ require 'fileutils'
33require 'benchmark'
44require 'pathname'
55require 'shellwords'
6+ require 'English'
67
7- ROOT = Pathname File . expand_path ( [ '..' , '..' ] . join ( File ::Separator ) , __FILE__ )
8- TMP_DIR = File . join ( ROOT , 'tmp/bench' )
8+ class Benchmarking
9+ ROOT = Pathname File . expand_path ( [ '..' , '..' ] . join ( File ::Separator ) , __FILE__ )
10+ TMP_DIR = File . join ( ROOT , 'tmp/bench' )
911
10- def temp_dir_empty?
11- Dir [ File . join ( TMP_DIR , '*' ) ] . none?
12- end
12+ attr_reader :prepend , :append
1313
14- def empty_temp_dir
15- FileUtils . mkdir_p ( TMP_DIR )
16- Dir [ File . join ( TMP_DIR , '*' ) ] . each do | file |
17- FileUtils . rm ( file )
14+ def initialize ( prepend : '' , append : '' )
15+ @prepend = prepend
16+ @append = append
17+ refresh_temp_dir if temp_dir_empty?
1818 end
19- end
2019
21- def fill_temp_dir
22- Dir [ File . join ( ROOT , 'test' , 'benchmark' , '*.rb' ) ] . each do |file |
23- FileUtils . cp ( file , File . join ( TMP_DIR , File . basename ( file ) ) )
20+ def temp_dir_empty?
21+ Dir [ File . join ( TMP_DIR , '*' ) ] . none?
2422 end
25- at_exit { empty_temp_dir }
26- end
2723
28- def refresh_temp_dir
29- empty_temp_dir
30- fill_temp_dir
31- end
24+ def empty_temp_dir
25+ FileUtils . mkdir_p ( TMP_DIR )
26+ Dir [ File . join ( TMP_DIR , '*' ) ] . each do |file |
27+ FileUtils . rm ( file )
28+ end
29+ end
3230
33- def benchmark_tests
34- refresh_temp_dir if temp_dir_empty?
35- system ( "bundle exec ruby -Ilib:test #{ Shellwords . shellescape ( TMP_DIR ) } /*_benchmark.rb" )
36- end
31+ def fill_temp_dir
32+ Dir [ File . join ( ROOT , 'test' , 'benchmark' , '*.rb' ) ] . each do |file |
33+ FileUtils . cp ( file , File . join ( TMP_DIR , File . basename ( file ) ) )
34+ end
35+ at_exit { empty_temp_dir }
36+ end
3737
38- def current_branch
39- @current_branch ||= `cat .git/HEAD | cut -d/ -f3,4,5` . chomp
40- end
38+ def refresh_temp_dir
39+ empty_temp_dir
40+ fill_temp_dir
41+ end
4142
42- def checkout_ref ( ref )
43- puts `git checkout #{ ref } ` . chomp
44- abort "Checkout failed: #{ ref } , #{ $? . exitstatus } " unless $? . success?
45- end
43+ def benchmark_tests
44+ tmp_dir = Shellwords . shellescape ( TMP_DIR )
45+ system ( " #{ prepend } bundle exec ruby -Ilib:test #{ tmp_dir } /*_benchmark.rb #{ append } " )
46+ end
4647
47- def benchmark
48- refresh_temp_dir
49- ref = current_branch
48+ def current_branch
49+ @current_branch ||= `cat .git/HEAD | cut -d/ -f3,4,5` . chomp
50+ end
5051
51- actual = run_benchmark_at_ref ref
52- master = run_benchmark_at_ref 'master'
52+ def checkout_ref ( ref )
53+ puts `git checkout #{ ref } ` . chomp
54+ abort "Checkout failed: #{ ref } , #{ $CHILD_STATUS. exitstatus } " unless $CHILD_STATUS. success?
55+ end
5356
54- checkout_ref ( ref )
57+ def benchmark_refs ( ref1 : nil , ref2 : nil )
58+ ref0 = current_branch
59+ ref1 ||= current_branch
60+ ref2 ||= 'master'
5561
56- puts "\n \n Results ============================\n "
57- puts "------------------------------------~> (Branch) MASTER"
58- puts master
59- puts "------------------------------------\n \n "
62+ actual = run_benchmark_at_ref ( ref1 )
63+ master = run_benchmark_at_ref ( ref2 )
6064
61- puts "------------------------------------~> (Actual Branch) #{ ref } "
62- puts actual
63- puts "------------------------------------"
64- end
65+ checkout_ref ( ref0 )
6566
66- def run_benchmark
67- response = Benchmark . realtime {
68- benchmark_tests
69- }
70- benchmark_tests
71- response
72- end
67+ <<-REPORT
7368
74- def run_benchmark_at_ref ( ref )
75- checkout_ref ( ref )
76- run_benchmark
69+
70+ Results ============================
71+ ------------------------------------~> (Branch) #{ ref2 . upcase }
72+ #{ master } (seconds)
73+ ------------------------------------
74+
75+
76+
77+ ------------------------------------~> (Actual Branch) #{ ref1 . upcase }
78+ #{ actual } (seconds)
79+ ------------------------------------
80+ REPORT
81+ rescue Exception # rubocop:disable Lint/RescueException
82+ checkout_ref ( ref0 )
83+ raise
84+ end
85+
86+ def run_benchmark
87+ bundle
88+ benchmark_tests # warmup
89+ parse_measurement Benchmark . measure {
90+ benchmark_tests
91+ }
92+ end
93+
94+ def run_benchmark_at_ref ( ref )
95+ checkout_ref ( ref )
96+ run_benchmark
97+ end
98+
99+ def bundle
100+ system ( 'rm -f Gemfile.lock; bundle check || bundle --local --quiet || bundle --quiet' )
101+ end
102+
103+ def parse_measurement ( measurement )
104+ user = measurement . utime
105+ system = measurement . stime
106+ total = measurement . total
107+ real = measurement . real
108+ {
109+ :real => real ,
110+ :total => total ,
111+ :user => user ,
112+ :system => system
113+ }
114+ end
77115end
78116
79- if $0 == __FILE__
80- benchmark
117+ if $PROGRAM_NAME == __FILE__
118+ benchmarking = Benchmarking . new ( prepend : 'TIMES=1000' , append : '> /dev/null' )
119+ test_type = ARGV [ 0 ]
120+ case test_type
121+ when 'current'
122+ puts "Ran in #{ benchmarking . run_benchmark } seconds."
123+ else
124+ # Default: Compare current_branch to master
125+ # Optionally: pass in two refs as args to `bin/bench`
126+ # TODO: Consider checking across more revisions, to automatically find problems.
127+ puts benchmarking . benchmark_refs ( ref1 : ARGV [ 0 ] , ref2 : ARGV [ 1 ] )
128+ end
81129end
0 commit comments