diff --git a/tools/performance_compare.v b/tools/performance_compare.v index 461bcc678c..6428f908b0 100644 --- a/tools/performance_compare.v +++ b/tools/performance_compare.v @@ -11,17 +11,17 @@ const ( ) struct Context { - cwd string // current working folder + cwd string // current working folder mut: - vc_repo_url string // the url of the vc repository. It can be a local folder path, which is usefull to eliminate network operations... - workdir string // the working folder (typically /tmp), where the tool will write - a string // the full path to the 'after' folder inside workdir - b string // the full path to the 'before' folder inside workdir - vc string // the full path to the vc folder inside workdir. It is used during bootstrapping v from the C source. + vc_repo_url string // the url of the vc repository. It can be a local folder path, which is usefull to eliminate network operations... + workdir string // the working folder (typically /tmp), where the tool will write + a string // the full path to the 'after' folder inside workdir + b string // the full path to the 'before' folder inside workdir + vc string // the full path to the vc folder inside workdir. It is used during bootstrapping v from the C source. commit_before string // the git commit for the 'before' state commit_after string // the git commit for the 'after' state - warmups int // how many times to execute a command before gathering stats - verbose bool // whether to print even more stuff + warmups int // how many times to execute a command before gathering stats + verbose bool // whether to print even more stuff hyperfineopts string // use for additional CLI options that will be given to the hyperfine command } fn new_context() Context { @@ -57,36 +57,34 @@ fn used_tools_must_exist(tools []string) { fn (c Context) compare_versions() { // Input is validated at this point... - //Cleanup artifacts from previous runs of this tool: + // Cleanup artifacts from previous runs of this tool: os.chdir( c.workdir ) run('rm -rf "$c.a" "$c.b" "$c.vc" ') // clone the VC source *just once per comparison*, and reuse it: run('git clone --quiet \'$c.vc_repo_url\' \'$c.vc\' ') - println('Comparing v compiler performance of commit $c.commit_before (before) vs commit $c.commit_after (after) ...') + println('Comparing V performance of commit $c.commit_before (before) vs commit $c.commit_after (after) ...') c.prepare_v( c.b , c.commit_before ) c.prepare_v( c.a , c.commit_after ) os.chdir( c.workdir ) + //The first is the baseline, against which all the others will be compared. + //It is the fastest, since hello_world.v has only a single println in it, c.compare_v_performance([ - //The first is the baseline, against which all the others will be compared. - //It is the fastest, since hello_world.v has only a single println in it, - 'vprod -debug -o source.c examples/hello_world.v', - 'vprod -o source.c examples/hello_world.v', - 'vprod -debug -o source.c compiler', - 'vprod -o source.c compiler', - 'vprod -o hello examples/hello_world.v', - 'vprod -o binary compiler', - + 'vprod @DEBUG@ -o source.c examples/hello_world.v', + 'vprod -o source.c examples/hello_world.v', + 'vprod @DEBUG@ -o source.c @COMPILER@', + 'vprod -o source.c @COMPILER@', + 'vprod -o hello examples/hello_world.v', + 'vprod -o binary @COMPILER@', ///////////////////////////////////////////////////////// - - 'v -debug -o source.c examples/hello_world.v', - 'v -o source.c examples/hello_world.v', - 'v -debug -o source.c compiler', - 'v -o source.c compiler', - 'v -o hello examples/hello_world.v', - 'v -o binary compiler', - ]) + 'v @DEBUG@ -o source.c examples/hello_world.v', + 'v -o source.c examples/hello_world.v', + 'v @DEBUG@ -o source.c @COMPILER@', + 'v -o source.c @COMPILER@', + 'v -o hello examples/hello_world.v', + 'v -o binary @COMPILER@', + ]) } @@ -138,11 +136,12 @@ fn (c &Context) prepare_v( cdir string, commit string ) { run('git clean -f') c.prepare_vc_source( cdir, commit ) + source_location := if os.exists('v.v') { 'v.v' } else { 'compiler/' } println('Making v and vprod compilers in $cdir') run(command_for_building_v_from_c_source) - run('./cv -o v compiler/ ') - run('./cv -prod -o vprod compiler/ ') + run('./cv -o v $source_location') + run('./cv -prod -o vprod $source_location') run('cp cv cv_stripped') run('cp v v_stripped') @@ -156,21 +155,32 @@ fn (c &Context) prepare_v( cdir string, commit string ) { run('upx -qqq --lzma v_stripped_upxed') run('upx -qqq --lzma vprod_stripped_upxed') - show_sizes_of_files(["$cdir/cv", "$cdir/cv_stripped", "$cdir/cv_stripped_upxed"]) - show_sizes_of_files(["$cdir/v", "$cdir/v_stripped", "$cdir/v_stripped_upxed"]) - show_sizes_of_files(["$cdir/vprod", "$cdir/vprod_stripped", "$cdir/vprod_stripped_upxed"]) + show_sizes_of_files(["$cdir/cv", "$cdir/cv_stripped", "$cdir/cv_stripped_upxed"]) + show_sizes_of_files(["$cdir/v", "$cdir/v_stripped", "$cdir/v_stripped_upxed"]) + show_sizes_of_files(["$cdir/vprod", "$cdir/vprod_stripped", "$cdir/vprod_stripped_upxed"]) println("V version is: " + run("$cdir/v --version") + " , local source commit: " + run("git rev-parse --short --verify HEAD") ) - println('Source lines in compiler/ ' + run('wc compiler/*.v | tail -n -1') ) + println('Source lines of the compiler: ' + run('wc v.v compiler/*.v vlib/compiler/*.v | tail -n -1') ) } - fn (c Context) compare_v_performance( commands []string ) { println('---------------------------------------------------------------------------------') println('Compare v performance when doing the following commands:') + + source_location_a := if os.exists('$c.a/v.v') { 'v.v' } else { 'compiler/' } + source_location_b := if os.exists('$c.b/v.v') { 'v.v' } else { 'compiler/' } + timestamp_a, _ := line_to_timestamp_and_commit(run('cd $c.a/ ; git rev-list -n1 --timestamp HEAD')) + timestamp_b, _ := line_to_timestamp_and_commit(run('cd $c.b/ ; git rev-list -n1 --timestamp HEAD')) + debug_option_a := if timestamp_a > 1570877641 { '-g' } else { '-debug' } + debug_option_b := if timestamp_b > 1570877641 { '-g' } else { '-debug' } + mut hyperfine_commands_arguments := []string for cmd in commands { println(cmd) } - for cmd in commands { hyperfine_commands_arguments << ' \'cd ${c.b:30s} ; ./$cmd \' ' } - for cmd in commands { hyperfine_commands_arguments << ' \'cd ${c.a:30s} ; ./$cmd \' ' } + for cmd in commands { + hyperfine_commands_arguments << ' \'cd ${c.b:30s} ; ./$cmd \' '.replace_each(['@COMPILER@', source_location_b, '@DEBUG@', debug_option_b]) + } + for cmd in commands { + hyperfine_commands_arguments << ' \'cd ${c.a:30s} ; ./$cmd \' '.replace_each(['@COMPILER@', source_location_a, '@DEBUG@', debug_option_a]) + } /////////////////////////////////////////////////////////////////////////////// cmd_stats_file := os.realpath([ c.workdir, 'v_performance_stats.json'].join(os.path_separator)) comparison_cmd := 'hyperfine $c.hyperfineopts '+ @@ -209,22 +219,22 @@ fn main(){ fp.skip_executable() fp.limit_free_args(1,2) show_help:=fp.bool('help', false, 'Show this help screen\n') - + context.vc_repo_url = fp.string('vcrepo', 'https://github.com/vlang/vc', '' + 'The url of the vc repository. You can clone it \n'+ flag.SPACE+'beforehand, and then just give the local folder \n'+ - flag.SPACE+'path here. That will eliminate the network ops \n'+ + flag.SPACE+'path here. That will eliminate the network ops \n'+ flag.SPACE+'done by this tool, which is useful, if you want \n'+ flag.SPACE+'to script it/run it in a restrictive vps/docker.\n') - + context.verbose = fp.bool('verbose', false, 'Be more verbose\n') context.hyperfineopts = fp.string('hyperfine_options', '', '' + 'Additional options passed to hyperfine.\n'+ flag.SPACE+'For example on linux, you may want to pass:\n'+ flag.SPACE+' --hyperfine_options "--prepare \'sync; echo 3 | sudo tee /proc/sys/vm/drop_caches\'" \n') - + context.workdir = os.realpath( fp.string('workdir', '/tmp', 'A writable folder, where the comparison will be done.') ) if( show_help ){ println( fp.usage() )