Performance

obstcl's light weight has paid off in performance. It is faster than sterno and tcl++, but (not surprisingly) slower than [incr Tcl]. Here are the results -- you can see the test files in the test directory. Times were measured on an unloaded UltraSparc with a gazigabyte of RAM and a gazillion Hz clock.

[incr Tcl] tcl++ sterno obstcl obstcl*
Define class 1580 19745 3037 3779
Create object 200 4778 3033 1049
Empty method 35 885 688 209 102
Empty with args 83 718 706 259 106
Sum three args 144 723 713 284 113
Call self 116 181 543 101
Access scalar 16 18 16 16
Access array 22 32 32 33

The rightmost column, marked "obstcl*," show calling times for calls of the form namespace eval Foo {empty $foo} instead of the more object-oriented $foo empty. (Note that this calling method still gives correct overloading of "virtual methods.")

The test were mostly intended to show calling overheads. In methods that are larger, the overheads would probably be less significant.

obstcl has the drawback that the creation and calling overhead increases with the number of instance variables. To get a feel for this, I wrote scripts that create and call an object with 1, 10, and 100 instance variables. Here are the results to create and call the object:

[incr Tcl] tcl++ sterno obstcl obstcl*
1 instance variable, create 196 4478 2706 969
10 instance variables, create 368 4573 4324 1387
100 instance variables, create 2612 19581 24790 5387
1 instance variable, call 82 928 748 196 98
10 instance variables, call 92 735 1574 388 265
100 instance variables, call 75 737 10116 2493 2032

So it turns out that at around 20, obstcl's calling overhead reaches that of tcl++, which has a relatively constant overhead. The reason is that tcl++ does not access scalar variables by name, but places them into an array, so that each access must be of the form set v(foo) $v(bar) instead of the more obvious set foo $bar. It would be simple to modify obstcl to do this, I just don't like it much.

Besides, if you have more than 20 instance variables in an object, you probably should be using [incr Tcl] anyway...