Tpett - Tcl Proc Evaluator/Timer/Tester Directions to find it at [Stu] [Stu] - 2007/10/18 Created this page. As a testament to Tcl and this Wiki, this program took about a day to write initially and a few more hours to finish off a quickie 0.1 version. Pretty good since I hadn't done any gui programming in quite some time (years?) and had never really used a [canvas]. Getting the gui to [grid] properly took maybe 20% of the time - grrr. ---- From the help: "Tpett is for to test and graph Tcl proc performance, allowing for simple proc performance comparisons." Screenshot: [http://img514.imageshack.us/img514/5868/tpettchrscrub4.gif] The distribution files contain the source and some examples but for you masochistic types, here's the source code (some of it is not pretty, especially the graphing code which is not quite right in the head. You've been warned): #! /bin/sh # \ exec tclsh "$0" ${1+"$@"} package require Tk # Tpett - Tcl Proc Evaluator/Timer/Tester # 0.1 # October 2007 # Stuart Cassoff # With lots of help from the Tcler's Wiki # namespace eval tpett { variable cfg variable results set cfg(prog) {Tpett} set cfg(name) {Tcl Proc Evaluator/Timer/Tester} set cfg(ver) {0.1} set cfg(date) {October 2007} set cfg(author) {Stuart Cassoff} set cfg(license) {BSD} set cfg(smooth) 1 set cfg(title) {} set cfg(xaxistitle) {} set cfg(colors) [list cornsilk gold goldenrod burlywood coral2 chartreuse cyan brown green blue white papayawhip bisque] set cfg(procs) {} array set results {} } proc tpett::sourcefile {what fn} { variable gui variable cfg $gui($what) delete 1.0 end set f [open $fn r]; $gui($what) insert end [read $f]; close $f } proc tpett::loadfile {what} { rename ::proc ::tpett::tpettproc rename ::tpett::_proc ::proc set fn [tk_getOpenFile -title [expr {$what eq {pt} ? {To Test} : {Run Test}}]] rename ::proc ::tpett::_proc rename ::tpett::tpettproc ::proc if {$fn ne {}} { sourcefile $what $fn } } proc tpett::setagoodexample {} { variable gui $gui(pt) delete 1.0 end $gui(pt) insert end {proc toupper {string} { return [string toupper $string] } proc tolower {string} { return [string tolower $string] } proc totitle {string} { return [string totitle $string] } proc tonothing {string} {} } $gui(tt) delete 1.0 end $gui(tt) insert end {title "String Command Tests" xaxistitle "Input String Size" set times 1000 foreach p [getprocs] { for {set i 10} {$i <= 100} {incr i 10} { set data [string repeat Aa $i] set size [string length $data] test $p $data $size $times } } } evaltext_pt evaltext_tt } proc tpett::setinfo {} { variable cfg variable gui $gui(thelp) insert end [subst {$cfg(prog) - $cfg(name) $cfg(ver) $cfg(date) $cfg(author) License: $cfg(license) $cfg(prog) is for to test and graph Tcl proc performance, allowing for simple proc performance comparisons. Put procs to test in "To Test". Click "Eval". Put test code in "Run Test". Click "Eval". When "To Test" code is evaluated, $cfg(prog) will automatically accumulate procs. Accumulated procs will show in "Procs" listbox on right. Double click on a proc in "Procs" listbox to select or deselect it for testing. To test, the command \[test\] must be called with the following parameters: procname: Name of proc to test. argument: Argument to proc. Only one argument possible now. Maybe more later. testpoint: Value of testpoint; ex: \[string length \$inputData\]. times: How many times (as in the \[time\] command) to run the proc. Optional; default: 1. The command \[getprocs\] will return a list of selected accumulated procs, The command \[title\] will set the title of the graph; ex: title "String Command Tests". The command \[xaxistitle\] will set the title of the x-axis of the graph; ex: xaxistitle "Input String Size". Check or uncheck "Smooth" for desired smoothiness. Click "Exit" button or press "Esc" key to exit program. Unplugging computer will also work. Click one of the "Load" buttons to enable loading of program data file information from rigid spinning disk platter, solid state storage, magnetic drum, conga drum, abacus, usb-connected windchimes or extraterrestrial transmission. Click "Example" button or run without args to get example usage. Run from command line: \$ ./tpett.tcl totest.tcl runtest.tcl }] } proc tpett::setupgui {{w {}}} { variable cfg variable gui set gui(cw) 600 set gui(ch) 400 set ns [namespace current] grid [set gui(pw) [panedwindow $w.pw]] -sticky nsew $gui(pw) add [canvas [set gui(cnv) $gui(pw).cnv] -width $gui(cw) -height $gui(ch) -bg black] $gui(pw) add [set gui(thelp) [text $gui(pw).thelp -width 10]] $gui(pw) sash place 0 65535 0 grid ^ [set f [frame $w.f0]] -sticky ns grid [label $f.lh -text {<- Slide For Help}] -pady 3 -sticky nw grid [label $f.ll -text Procs] -sticky s grid [set gui(lb) [listbox $f.lb -width 2 -listvariable ${ns}::cfg(procs)]] -sticky nsew grid [checkbutton $f.sb -text Smooth -command ${ns}::graph -variable ${ns}::cfg(smooth)] -sticky sew grid [button $f.eb -text Example -command ${ns}::setagoodexample] -sticky sew grid [button $f.eq -text Exit -command exit] -sticky sew set tw 80 set th 10 grid [text [set gui(pt) $w.pt] -width $tw -height $th] -sticky nsew grid ^ [set f [frame $w.f1]] -sticky nsew grid [label $f.lt -text {To Test}] -sticky ns grid [button $f.plb -text Load -command [list ${ns}::loadfile pt]] -sticky sew grid [button $f.pb -text Eval -command ${ns}::evaltext_pt] -sticky sew set tw 80 set th 11 grid [text [set gui(tt) $w.tt] -width $tw -height $th] -sticky nsew grid ^ [set f [frame $w.f2]] -sticky nsew grid [label $f.lr -text {Run Test}] -sticky ns grid [button $f.tlb -text Load -command [list ${ns}::loadfile tt]] -sticky sew grid [button $f.tb -text Eval -command ${ns}::evaltext_tt] -sticky sew grid columnconfigure . 0 -weight 1 foreach r [list 0 1 2 3 4 5] wght [list 0 1 0 1 0 1] { grid rowconfigure . $r -weight $wght } grid rowconfigure $w.f0 2 -weight 1 foreach f [list 1 2] { grid columnconfigure $w.f$f 0 -weight 1 grid rowconfigure $w.f$f 0 -weight 1 } bind . exit bind $gui(cnv) ${ns}::graph bind .f0.lb [list ${ns}::procselect %W] wm title . "$cfg(prog) $cfg(ver)" } proc ::tpett::procselect {w} { set csc [$w itemcget [$w curselection] -foreground] if {$csc eq {} || $csc eq [$w cget -foreground]} { set fg goldenrod set sfg $fg } else { set fg [$w cget -foreground] set sfg $fg } $w itemconfigure [$w curselection] -foreground $fg -selectforeground $sfg } proc tpett::evaltext_pt {} { variable gui variable cfg set cfg(procs) {} eval [$gui(pt) get 1.0 end] } proc tpett::evaltext_tt {} { variable gui reset namespace eval [namespace current] [$gui(tt) get 1.0 end] graph } proc tpett::title {title} { variable cfg set cfg(title) $title } proc tpett::xaxistitle {title} { variable cfg set cfg(xaxistitle) $title } proc tpett::graph {} { variable cfg variable gui variable results if {[llength [array names results]] == 0} { return } set cw [winfo width $gui(cnv)] set ch [winfo height $gui(cnv)] set gox 130 set goy 70 set gw [expr {$cw - ($gox * 2)}] set gh [expr {$ch - ($goy * 2)}] set ln {} set lx {} set ly {} foreach r [lsort -dictionary [array names results]] { lappend ln [lindex [split $r ,] 0] lappend lx [lindex [split $r ,] 1] lappend ly $results($r) } set minx [lindex $lx 0] set miny [lindex [lsort -integer $ly] 0] set maxx [lindex $lx end] set maxy [lindex [lsort -integer $ly] end] set scalex [expr {($gw * 1.0) / ($maxx * 1.0)}] set scaley [expr {($gh * 1.0) / ($maxy * 1.0)}] foreach n [lsort -unique $ln] c $cfg(colors) { set clrs($n) $c } $gui(cnv) delete all $gui(cnv) create text [expr {$gox + (($gw - 0) / 2)}] [expr {20}] -fill red -text $cfg(title) -font {Helvetica 16} set l {} set nn [lindex $ln 0] foreach n $ln x $lx y $ly { if {$nn ne $n} { $gui(cnv) create line $l -fill $clrs($nn) -smooth $cfg(smooth) set nn $n set l {} } lappend l [expr {$gox + int(($x - $minx) * $scalex)}] [expr {$goy + $gh - int(($y - $miny)* $scaley)}] } $gui(cnv) create line $l -fill $clrs($nn) -smooth $cfg(smooth) set bb 10 $gui(cnv) create rectangle [expr {$gox - $bb}] [expr {$goy - $bb}] [expr {$gw + $gox + $bb}] [expr {$gh + $goy + $bb}] -outline red set x [expr {$gox - 16}] for {set i $miny} { $i <= $maxy} {set i [expr {$i + (($maxy - $miny) / 10)}]} { set y [expr {$gh + $goy - int(($i - $miny) * $scaley)}] $gui(cnv) create line $x $y [expr {$x + 5}] $y -fill red $gui(cnv) create text [expr {$x - 15}] $y -fill red -text $i } $gui(cnv) create text [expr {$gox - 55}] [expr {$goy + (($gh - 0) / 2)}] -fill red -text T\n\ i\nm\ne\n\n\u03bc\ns set y [expr {$gh + $goy + $bb + 2}] for {set i $minx} { $i <= $maxx} {set i [expr {$i + (($maxx - $minx) / 10)}]} { set x [expr {$gox + int(($i - $minx) * $scalex)}] $gui(cnv) create line $x $y $x [expr {$y + 5}] -fill red $gui(cnv) create text $x [expr {$y + 15}] -fill red -text $i } $gui(cnv) create text [expr {$gox + (($gw - 0) / 2)}] [expr {$y + 35}] -fill red -text $cfg(xaxistitle) set tx [expr {10}] set ty [expr {10}] set th [expr {20}] foreach n [lsort -unique $ln] { $gui(cnv) create text $tx $ty -text $n -fill $clrs($n) -anchor nw incr ty $th } } proc tpett::test {procname argument testpoint {times {1}}} { variable results set results($procname,$testpoint) [expr {int([lindex [time [list $procname $argument] $times] 0])}] } proc tpett::reset {} { variable results array unset results array set results {} } proc tpett::print {} { variable results parray results } proc tpett::getprocs {} { variable cfg variable gui set procs {} for {set i 0} {$i < [$gui(lb) index end]} {incr i} { set csc [$gui(lb) itemcget $i -foreground] if {$csc eq {} || $csc eq [$gui(lb) cget -foreground]} { lappend procs [$gui(lb) get $i] } } return $procs } proc tpett::usage {} { variable cfg puts "$cfg(prog) $cfg(ver): $cfg(name)" puts {Usage: tpett.tcl [totest.file] [runtest.file]} } # proc tpett::tpettproc {name args body} { if {[string range $name 0 5] ne {::tk::} && [lsearch $::tpett::cfg(procs) $name] == -1} { lappend ::tpett::cfg(procs) $name } ::tpett::_proc $name $args $body } rename ::proc ::tpett::_proc rename ::tpett::tpettproc ::proc # namespace eval tpett { setupgui setinfo if {$::argc == 0} { setagoodexample } if {$::argc > 2 || ($::argc >= 1 && [lsearch $::argv {-?}] != -1)} { usage exit } if {$::argc >= 1} { sourcefile pt [lindex $::argv 0] } if {$::argc == 2} { sourcefile tt [lindex $::argv 1] evaltext_pt evaltext_tt } } # EOF <>Performance