In [Elegance vs. performance] [RS] et al. bring up some interesting results, and a nice graph widget to visualise them. ([DKF] elides stuff in favour of a much more compacted and effective version; see the end of this page) Here are some interesting and counter-intuitive results: First we time compilation of trivial procs of increasing length proc sum1 list { foreach i $list {append body "set v$i $i" \n} proc x1 {} $body } proc sum2 list { foreach i $list {append body "set v$i $i" \n} proc x2 {} $body x2 } [http://chinix.com/~colin/speed2.jpg] Now for the surprise - we generate a series of procs with increasingly nested evals. proc sum1 list { set body 0 foreach i $list {set body "\[set v$i $body]"} proc x1 {} "set N $body" } proc sum2 list { set body 0 foreach i $list {set body "\[set v$i $body]"} proc x2 {} "set N $body" x2 } [http://chinix.com/~colin/speed3.jpg] ---- Turns out that it's the parser that's the problem, after discussion with dkf. Here's some code that demonstrates it; the green line is running a pre-compiled proc. proc sum1 list { set body 0 foreach i $list {set body "\[set v $body]"} proc x1 {} "set N $body" } proc sum2 list { set body 0 foreach i $list {set body "\[set v $body]"} proc x2_[llength $list] {} "set N $body" x2_[llength $list] } proc sum3 list { x2_[llength $list] } and here's the resulting plot: [http://chinix.com/~colin/speed6.jpg] ---- [TFW] ''24 Feb 2004'' Looking at the parser, tokens are built up in reverse order (primarily in ''PrependSubExprTokens''), which uses a memmove to shift the existing tokens to the right and inserts the new tokens. When parsing a short line, there isn't much of a penalty; however as expressions grow larger this could be the root cause of the quadratic performance penalty. Another releated issue is CompileSubExpr can recursively call itself during the parse, which can cause a stack overflow. expr "[string repeat +1 10000]" ---- [DKF]: Let's regularize and standardize this. It's getting too hard to track what is going on. package require Tk proc plotGraph {conversionExpr args} { wm title . "Plotting using $conversionExpr" pack [canvas .c -bg white -width 500 -height 500] -expand 1 array set color { 1 red 2 blue 3 green 4 black } set i 0 foreach tag $args { .c create line 0 500 0 500 -fill $color([incr i]) -tag $tag } set list {} for {set i 1} {$i<450} {incr i} { lappend list 1 1 foreach func $args { set t [lindex [time {$func $list}] 0] .c coords $func [concat [.c coords $func] $i [expr {500-[expr $conversionExpr]}]] } update } } proc sum1 list { # Script construction set n [llength $list] proc x2_$n {} "set N [string repeat {[set v } $n]0[string repeat {]} $n]" } proc sum2 list { # Compilation and execution x2_[llength $list] } proc sum3 list { # Just execution x2_[llength $list] } #plotGraph {$t} sum1 sum2 sum3 ;# Plots things normally plotGraph {sqrt($t)} sum1 sum2 sum3 ;# Plots so straight-line = quadratic function #plotGraph {log($t)} sum1 sum2 sum3 ;# Plots si straight-line = exponential function ---- [Category Performance]