v / .github / workflows / compare_pr_to_master.v
171 lines · 151 sloc · 6.03 KB · e12ba2b67e2cae2c06ab407bb8bc3e4d56548dc3
Raw
1import os
2import time
3
4const compare_prod = '-prod' in os.args
5
6const cleanup_tmp = '-no-cleanup' !in os.args
7
8const fetch_remote = '-no-fetch' !in os.args
9
10fn gbranch() string {
11 return os.execute(r'git branch --list|grep ^\*').output.trim_left('* ').trim_space()
12}
13
14fn gcommit() string {
15 return os.execute(r'git rev-parse --short=7 HEAD').output.trim_left('* ').trim_space()
16}
17
18fn r(cmd string) {
19 res := os.system(cmd)
20 if res != 0 {
21 eprintln('> failed running: `${cmd}`')
22 exit(1)
23 }
24}
25
26fn xtime(cmd string) {
27 $if linux {
28 r('/usr/bin/time -f "CPU: %Us\tReal: %es\tElapsed: %E\tRAM: %MKB\t%C" ${cmd}')
29 return
30 }
31 $if macos {
32 r('/opt/homebrew/bin/gtime -f "CPU: %Us\tReal: %es\tElapsed: %E\tRAM: %MKB\t%C" ${cmd}')
33 return
34 }
35 // Pure V fallback - no memory stats, but better than nothing ...
36 before := time.now()
37 r(cmd)
38 after := time.now()
39 delta_time := after - before
40 println('> Elapsed time: ${delta_time.milliseconds()} ms, for cmd: ${cmd}')
41}
42
43fn show_size(fpath string) {
44 println('>Size of ${fpath:20s}: ${os.file_size(fpath):10}')
45}
46
47fn compare_size(fpath1 string, fpath2 string) {
48 size1 := os.file_size(fpath1)
49 size2 := os.file_size(fpath2)
50 diff_ := i64(size2) - i64(size1)
51 println('>>>>>> size("${fpath2:17}") - size("${fpath1:17}") = ${size2:10} - ${size1:10} = ${diff_:10}')
52}
53
54fn vcompare(vold string, vnew string) {
55 r("v repeat --nmaxs 7 -R 3 '${vold} -check-syntax examples/hello_world.v' '${vnew} -check-syntax examples/hello_world.v'")
56 r("v repeat --nmaxs 7 -R 3 '${vold} -check examples/hello_world.v' '${vnew} -check examples/hello_world.v'")
57 r("v repeat --nmaxs 7 -R 3 '${vold} -no-parallel -o ohw.c examples/hello_world.v' '${vnew} -no-parallel -o nhw.c examples/hello_world.v'")
58 compare_size('ohw.c', 'nhw.c')
59 r("v repeat --nmaxs 7 -R 3 '${vold} -no-parallel -o ohw.exe examples/hello_world.v' '${vnew} -no-parallel -o nhw.exe examples/hello_world.v'")
60 compare_size('ohw.exe', 'nhw.exe')
61
62 r("v repeat --nmaxs 7 -R 3 '${vold} -check-syntax cmd/v' '${vnew} -check-syntax cmd/v'")
63 r("v repeat --nmaxs 7 -R 3 '${vold} -check cmd/v' '${vnew} -check cmd/v'")
64 r("v repeat --nmaxs 7 -R 3 '${vold} -no-parallel -o ov.c cmd/v' '${vnew} -no-parallel -o nv.c cmd/v'")
65 compare_size('ov.c', 'nv.c')
66 r("v repeat --nmaxs 7 -R 3 '${vold} -no-parallel -o ov.exe cmd/v' '${vnew} -no-parallel -o nv.exe cmd/v'")
67 compare_size('ov.exe', 'nv.exe')
68}
69
70fn hline(header_message string) {
71 println('='.repeat(98))
72 println(header_message)
73}
74
75fn main() {
76 // The starting point, when this program should be started, is just after `gh pr checkout NUMBER`.
77 start := time.now()
78 pr_branch := gbranch()
79 pr_commit := gcommit()
80 hline('Current git branch: ${pr_branch}, commit: ${pr_commit}')
81 println(' Compiling new V executables from PR branch: ${pr_branch}, commit: ${pr_commit} ...')
82 // *not* using v self here is deliberate, so that the `v` executable itself, is not changed after running this script
83 xtime('./v -o vnew1 cmd/v')
84 xtime('./vnew1 -o vnew2 cmd/v')
85 xtime('./vnew2 -no-parallel -o vnew cmd/v')
86 xtime('./vnew -no-parallel -o nhw_current.c examples/hello_world.v')
87 xtime('./vnew -no-parallel -o nhw_current_gcc.c -cc gcc examples/hello_world.v')
88 xtime('./vnew -no-parallel -o nv_current.c cmd/v')
89 if compare_prod {
90 xtime('./vnew -no-parallel -prod -o vnew_prod cmd/v')
91 }
92 show_size('nhw_current.c')
93 show_size('nhw_current_gcc.c')
94 show_size('nv_current.c')
95 show_size('vnew')
96 if compare_prod {
97 show_size('vnew_prod')
98 }
99 r('rm -rf vnew1 vnew2')
100
101 if fetch_remote {
102 // make sure to always compare against the main V repo's master branch by default:
103 os.execute('git -C . remote add V_REPO https://github.com/vlang/v.git')
104 os.execute('git -C . fetch V_REPO')
105 os.execute('git branch -D v_repo_master')
106 os.execute('git branch -f --track v_repo_master V_REPO/master')
107 }
108
109 r('git checkout v_repo_master')
110 master_branch := gbranch()
111 hline(' Compiling old V executables from branch: ${master_branch}, commit: ${gcommit()} ...')
112 // Use `make` to bootstrap the old V from the C sources on the master branch,
113 // because the new V compiler may have breaking changes that prevent it from
114 // compiling the old code directly.
115 xtime('make -j4')
116 xtime('./v -o vold1 cmd/v')
117 xtime('./vold1 -no-parallel -o vold cmd/v')
118 xtime('./vold -no-parallel -o ohw_master.c examples/hello_world.v')
119 xtime('./vold -no-parallel -o ohw_master_gcc.c -cc gcc examples/hello_world.v')
120 xtime('./vold -no-parallel -o ov_master.c cmd/v')
121 if compare_prod {
122 xtime('./vold -no-parallel -prod -o vold_prod cmd/v')
123 show_size('vold_prod')
124 }
125 show_size('ohw_master.c')
126 show_size('ohw_master_gcc.c')
127 show_size('ov_master.c')
128 show_size('vold')
129 if compare_prod {
130 show_size('vold_prod')
131 }
132 r('rm -rf vold1')
133
134 hline('File sizes so far ...')
135 compare_size('ohw_master.c', 'nhw_current.c')
136 compare_size('ohw_master_gcc.c', 'nhw_current_gcc.c')
137 compare_size('ov_master.c', 'nv_current.c')
138 compare_size('vold', 'vnew')
139
140 r('git checkout ${pr_branch}')
141 // we are on the PR branch again
142 hline(' Measuring at PR branch: ${pr_branch}, commit: ${gcommit()} ...')
143 if compare_prod {
144 vcompare('./vold_prod', './vnew_prod')
145 } else {
146 vcompare('./vold', './vnew')
147 }
148 println('Done. Total time: ${(time.now() - start).seconds()} s.')
149
150 hline('Final summary for file diff sizes on their own branches:')
151 compare_size('ohw_master.c', 'nhw_current.c')
152 compare_size('ohw_master_gcc.c', 'nhw_current_gcc.c')
153 compare_size('ov_master.c', 'nv_current.c')
154 compare_size('vold', 'vnew')
155 if compare_prod {
156 compare_size('vold_prod', 'vnew_prod')
157 }
158
159 hline('Final summary for file diff sizes for generated files on the *current* branch:')
160 compare_size('ohw.c', 'nhw.c')
161 compare_size('ov.c', 'nv.c')
162 compare_size('ohw.exe', 'nhw.exe')
163 compare_size('ov.exe', 'nv.exe')
164
165 // After all the measurements are done, delete all the generated temporary files,
166 // except the `vold` and `vnew` compilers, so that they can be used later in manual
167 // experiments:
168 if cleanup_tmp {
169 r('rm -rf ohw* nhw* nv* ov*')
170 }
171}
172