Version 0 of Itcl overhead

Updated 2006-03-29 08:39:59

This page is about benchmarking Tcl's proc vs Itcl based code to see how much oveerhead Itcl adds and how to make it's performance better.

I decided to compare plain Tcl recursive calling vs Itcl inheriting, using chain and delegating.

If Itcl class has no variables and procs do not use any variables:

 ITcl: Chain 10 level deep      51.347
 ITcl: Chain 11 level deep      55.769
 ITcl: Chain 12 level deep      61.921
 ITcl: Chain 13 level deep      72.064
 ITcl: Chain 14 level deep      76.513
 ITcl: Chain 15 level deep      77.732
 ITcl: Chain 16 level deep      84.874
 ITcl: Chain 17 level deep      91.932
 ITcl: Chain 18 level deep     121.868
 ITcl: Chain 19 level deep      114.08
 ITcl: Chain 20 level deep     108.025
 ITcl: Delegate 10 level deep   32.479
 ITcl: Delegate 11 level deep   36.436
 ITcl: Delegate 12 level deep   39.776
 ITcl: Delegate 13 level deep   41.741
 ITcl: Delegate 14 level deep   45.113
 ITcl: Delegate 15 level deep   49.032
 ITcl: Delegate 16 level deep   52.265
 ITcl: Delegate 17 level deep   54.443
 ITcl: Delegate 18 level deep   93.945
 ITcl: Delegate 19 level deep   71.611
 ITcl: Delegate 20 level deep    70.01
 ITcl: Inherit 10 level deep    25.959
 ITcl: Inherit 11 level deep    28.699
 ITcl: Inherit 12 level deep    31.088
 ITcl: Inherit 13 level deep    33.196
 ITcl: Inherit 14 level deep    35.765
 ITcl: Inherit 15 level deep    38.178
 ITcl: Inherit 16 level deep    44.797
 ITcl: Inherit 17 level deep    43.085
 ITcl: Inherit 18 level deep    54.318
 ITcl: Inherit 19 level deep    47.477
 ITcl: Inherit 20 level deep    50.636
 Tcl:  Recursive 10 level deep  10.403
 Tcl:  Recursive 11 level deep  11.743
 Tcl:  Recursive 12 level deep  12.324
 Tcl:  Recursive 13 level deep  14.245
 Tcl:  Recursive 14 level deep  14.721
 Tcl:  Recursive 15 level deep  16.241
 Tcl:  Recursive 16 level deep  16.997
 Tcl:  Recursive 17 level deep  17.485
 Tcl:  Recursive 18 level deep  18.763
 Tcl:  Recursive 19 level deep  22.154
 Tcl:  Recursive 20 level deep  21.667

So it seems that inheriting and calling methods from the same object seems to be the fastest way and using chan is the worst way.

Now, the tclbench based test that did the trick:

 package require Itcl

 set itclvars 0
 set minlevel 10
 set maxlevel 20
 set iter 10000

 proc ::level1 {a b c d e} {
 }

 itcl::class ::class1 {
    public method level1 {a b c d e} {
         return 1
    }
 }
 itcl::class ::classI1 {
    inherit ::class1
 }

 itcl::class ::classD1 {
    inherit ::class1
 }

 itcl::class ::classC1 {
    public method level {a b c d e} {
         return 1
    }
 }

 for {set i 2} {$i <= $maxlevel} {incr i} {
    set varcode ""
    set varproccode ""
    set varitclcode ""
    set varlist [list]
    for {set j 0} {$j < $itclvars} {incr j} {
         set vn v${i}c${j}
         lappend varlist $vn
         append varcode "protected variable $vn 0" \n
         set ::$vn 0
         append varproccode "incr ::$vn" \n
         append varitclcode "incr $vn" \n
    }

    set ip [expr {$i-1}]

    proc ::level$i {a b c d e} "$varproccode \; return \[::level$ip \$a \$b \$c \$d \$e\]"

    itcl::class ::classD$i "
         $varcode
         public method level$i \{a b c d e\} \{
             $varitclcode
             return \[::oD$ip level$ip \$a \$b \$c \$d \$e\]
         \}
    "

    itcl::class ::classI$i "inherit ::classI$ip
         $varcode
         public method level$i \{a b c d e\} \{
             $varitclcode
             return \[level$ip \$a \$b \$c \$d \$e\]
         \}
    "

    itcl::class ::classC$i "inherit ::classC$ip
         $varcode
         public method level \{a b c d e\} \{
             $varitclcode
             return \[chain \$a \$b \$c \$d \$e\]
         \}
    "
 }

 for {set i 1} {$i <= $maxlevel} {incr i} {
    ::classI$i ::oI$i
    ::classD$i ::oD$i
    ::classC$i ::oC$i
 }

 if {[catch {
    ::oI$maxlevel level$maxlevel 1 2 3 4 5
    ::oD$maxlevel level$maxlevel 1 2 3 4 5
    ::oC2 level 1 2 3 4 5
    ::level2 1 2 3 4 5
 }]} {
    puts stderr $::errorInfo
    exit 1
 }
 for {set i $minlevel} {$i <= $maxlevel} {incr i} {
    bench -desc "Tcl:  Recursive [format %2d $i] level deep" -iter $iter \
         -body "::level$i a b c d e"

    bench -desc "ITcl: Inherit [format %2d $i] level deep" -iter $iter \
         -body "::oI$i level$i a b c d e"

    bench -desc "ITcl: Delegate [format %2d $i] level deep" -iter $iter \
         -body "::oD$i level$i a b c d e"

    bench -desc "ITcl: Chain [format %2d $i] level deep" -iter $iter \
         -body "::oC$i level a b c d e"
 }

If someone wishes to make improvements ot the code, please also update the benchmarks.