# $Id: bench_op.pir 21395 2007-09-19 17:08:10Z kjs $ =head1 TITLE bench_op - Benchmark one or more opcodes =head1 SYNOPSIS parrot bench_op.pir 'add $I0, $I1, $I2' parrot bench_op.pir --preops='newclass $P0, "Foo"' file_w_ops.pir parrot bench_op.pir --help =head1 DESCRIPTION The given opcode(s) are compiled into a sequence: .sub _entry0 .param int N .local int i # # preops go here # null i loop: # # ops go here # inc i lt i, N, loop .end so they should conform to Parrot Calling Conventions. The code gets executed with the PIR compiler - using symbolic variables is always ok. Output is the time in seconds for 1.000.000 instruction(s). =head1 OPTIONS =over 4 =item I<--times=N> Run the given opcode(s) in a loop I time. If no I<--times> options is given 100.000 is used. =item I<--verbose=i> Set I<--verbose> to 1 to see the total time. Set I<--verbose> to 2 to see the compiled programs. =item I<--preops='opcode(s)'> Execute the given opcodes in front of the loop. This is needed for ops, that have side effects like B. =item I<--help> Print a short description and exit. =item I<--version> Print program version and exit. =back =cut .const string VERSION = "0.1.1" .sub main :main .param pmc argv load_bytecode "Getopt/Obj.pbc" .local int times times = 100000 .local int verbose verbose = 0 # Specification of command line arguments. .local pmc getopts getopts = new "Getopt::Obj" # getopts."notOptStop"(1) push getopts, "version" push getopts, "verbose=i" push getopts, "help" push getopts, "times=i" push getopts, "preops=s" .local string program shift program, argv .local pmc opt opt = getopts."get_options"(argv) .local int argc argc = argv unless argc goto do_help .local int def def = defined opt unless def goto do_help def = defined opt["version"] if def goto do_def def = defined opt["help"] if def goto do_help def = defined opt["times"] unless def goto default_times times = opt["times"] default_times: def = defined opt["verbose"] unless def goto default_verbose verbose = opt["verbose"] default_verbose: .local string preops def = defined opt["preops"] unless def goto default_preops preops = opt["preops"] default_preops: _run( argv, times, verbose, preops) end do_def: print program print ": Version " print VERSION print "\n" end do_help: print program print " [--help] [--version] [--verbose=i]] [--times=N] \\ \n" print "\t[--preops='op(s)'] file | opcode\n" print "\nRun opcode on commandline or from file times.\n" print "s. perldoc -F " print program print "\n" end .end .sub _run .param pmc argv .param int times .param int verbose .param string preops .local string op shift op, argv unless verbose goto no_v1 print "Running '" print op print "' " print times print " times\n" no_v1: # op may be a file or an opcode - try to open it .local pmc F open F, op, "<" .local int def def = defined F unless def goto op_is_op read op, F, 10000 # TODO use stat close F op_is_op: .local num empty empty = _bench(times, verbose, '', '') unless verbose goto no_v2 print "Empty " print empty print "\n" no_v2: .local num test .local num diff test = _bench(times, verbose, op, preops) diff = test - empty unless verbose goto no_v3 print "Total " print test print "\n" print "Prog " print diff print "\n" no_v3: test = diff * 1.0E6 test = test / times print "Time for 1 million instructions: " print test print "\n" .end .sub _bench .param int n .param int verbose .param string ops .param string preops .local pmc compiler .local pmc compiled .local int l .local string ls .local string prog length l, ops ls = l .local string entry_label entry_label = "_entry" . ls compreg compiler, "PIR" # TODO PASM option prog = ".sub " . entry_label prog = prog . "\n.param int N\n.local int i\nnull i\n" prog = prog . preops prog = prog . "\nloop:\n" prog = prog . ops prog = prog . "\ninc i\nlt i, N, loop\n.end\n" if verbose < 2 goto no_v2 print "\n#---------\n" print prog print "#---------\n" no_v2: compiled = compiler(prog) .local num now time now .local pmc entry find_global entry, entry_label entry(n) .local num later time later later = later - now .return(later) .end =head1 BUGS You can't use the variables I and I nor the labels I and I<_entry\d> in your opcodes. =head1 AUTHOR Leopold Toetsch =cut # Local Variables: # mode: pir # fill-column: 100 # End: # vim: expandtab shiftwidth=4: