Source:
package require critcl namespace import critcl::* cproc noop {} void {} cproc add {int x int y} int { return x + y; } cproc cube {int x} int { return x * x * x; } puts "add 123 456 : [add 123 456]" catch {add 1} err; puts "add 1 : $err" catch {add 1 2 3} err; puts "add 1 2 3 : $err" catch {add 0 zero} err; puts "add 0 zero : $err" proc sum {a b} { return [expr {$a+$b}] } proc pow3 {a} { return [expr {$a*$a*$a}] } proc ntimes {n cmd t} { set on $n set r {} while {[incr n -1] >= 0} { lappend r $cmd } set v [uplevel 1 [list time [join $r {; }] $t]] return [lreplace $v 0 0 [expr {[lindex $v 0]/(1.0*$on)}]] } puts "" puts "Tcl noop: [ntimes 100 {} 1000]" puts " C noop: [ntimes 100 {noop} 1000]" set a 1 set b 2 puts "" puts "Tcl expr: [ntimes 100 {expr {1+2}} 1000]" puts "Tcl vars: [ntimes 100 {expr {$a+$b}} 1000]" puts "Tcl sum: [ntimes 100 {sum 1 2} 1000]" puts " C add: [ntimes 100 {add 1 2} 1000]" puts " C vars: [ntimes 100 {add $a $b} 1000]" puts "" puts "Tcl expr: [ntimes 100 {expr {2*2*2}} 1000]" puts "Tcl vars: [ntimes 100 {expr {$b*$b*$b}} 1000]" puts "Tcl pow3: [ntimes 100 {pow3 2} 1000]" puts " C cube: [ntimes 100 {cube 2} 1000]" puts " C vars: [ntimes 100 {cube $b} 1000]"
Output (SuSE 7.1 Linux, PIII/650):
add 123 456 : 579 add 1 : wrong # args: should be "add x y" add 1 2 3 : wrong # args: should be "add x y" add 0 zero : expected integer but got "zero" Tcl noop: 0.01 microseconds per iteration C noop: 0.67 microseconds per iteration Tcl expr: 0.36 microseconds per iteration Tcl vars: 1.92 microseconds per iteration Tcl sum: 2.51 microseconds per iteration C add: 1.06 microseconds per iteration C vars: 2.66 microseconds per iteration Tcl expr: 0.7 microseconds per iteration Tcl vars: 2.83 microseconds per iteration Tcl pow3: 2.78 microseconds per iteration C cube: 0.96 microseconds per iteration C vars: 1.81 microseconds per iteration
JH:
In order to have this work with ActiveTcl (Tcl with tcllib), I had to change the first few lines of the critcl.tcl code to:
catch {package require md5} if {[llength [info commands ::md5::md5]]} { interp alias {} ::md5 {} ::md5::md5 }
and it provided some very nice performance numbers on just the md5 stuff:
(jeffh) 60 % time {md5 hello} 1000 801 microseconds per iteration (jeffh) 61 % time {md5c hello} 1000 4 microseconds per iteration
The catch... would break if there was already an "md5" command, wouldn't it? In fact, while I think I understand why that code is written in the way it is, is there a way to do things simpler? - JCW
Maybe the following is a solution:
if {[catch md5]} { catch {package require md5} } if {[catch md5]} { interp alias {} ::md5 {} ::md5::md5 }
It's still extremely messy and weak (brittle) IMO, and illustrates how we seem to be making it harder and harder to write readable, clean, solid code... :-(
Works on Win98 with mingw. IDG