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 iterationJH: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 iterationThe 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? - JCWMaybe 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

