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...