@@ -3,79 +3,127 @@ require 'fileutils'
3
3
require 'benchmark'
4
4
require 'pathname'
5
5
require 'shellwords'
6
+ require 'English'
6
7
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' )
9
11
10
- def temp_dir_empty?
11
- Dir [ File . join ( TMP_DIR , '*' ) ] . none?
12
- end
12
+ attr_reader :prepend , :append
13
13
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?
18
18
end
19
- end
20
19
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?
24
22
end
25
- at_exit { empty_temp_dir }
26
- end
27
23
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
32
30
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
37
37
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
41
42
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
46
47
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
50
51
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
53
56
54
- checkout_ref ( ref )
57
+ def benchmark_refs ( ref1 : nil , ref2 : nil )
58
+ ref0 = current_branch
59
+ ref1 ||= current_branch
60
+ ref2 ||= 'master'
55
61
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 )
60
64
61
- puts "------------------------------------~> (Actual Branch) #{ ref } "
62
- puts actual
63
- puts "------------------------------------"
64
- end
65
+ checkout_ref ( ref0 )
65
66
66
- def run_benchmark
67
- response = Benchmark . realtime {
68
- benchmark_tests
69
- }
70
- benchmark_tests
71
- response
72
- end
67
+ <<-REPORT
73
68
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
77
115
end
78
116
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
81
129
end
0 commit comments