For users of Tcl 8.0, 8.1 and 8.2, this code provides a route for executing
commands that improves over the performance of the eval
command by a substantial margin.
Tcl8 is much faster than Tcl7 for most things, but when you start to sling about large lists, something where it should excel, it starts to have trouble with the strain (I've got code where Tcl8 is actually slower than Tcl7 due to this problem), which is where this code comes in. One of the most common constructs I use in Tcl, especially when writing extensions, is [eval [list $command $arg1 $arg2 ...] $args] to perform an evaluation taking a variable number of arguments without substitution (and it is a case which I think it should be possible to optimise quite nicely within the compiler) and this code forms a drop-in replacement for that.
When compiled, this produces the command object:fasteval command ?arg ...? arglist (it is part of an object system that I'm working on) which appends arglist to the list of arguments, and the executes the command without using Tcl's eval. Note that there is no second round of evaluation - the arguments that object:fasteval sees are the arguments that the command sees. Indeed, since the internal representations are passed to the command, this has a particularly good effect on performance over eval, since strings are only used where actually necessary.
Bugs:
The special internal commands can go really badly wrong - in particular, using expr as the command under Tcl8.0a1 caused a really interesting crunch, as the process rapidly grew to (over) 24MB and hit the total memory ulimit I had set at the time. It is better not to tempt fate, though the cause of this (commands that only had an implementation through the compiler, and not through the conventional command mechanism) does seem to have been alleviated in later versions of Tcl...
If a command that has been referred to is redefined, deleted or renamed, unexpected things may happen. I intend to fix the problems with redefinition and deletion, but renaming is fairly difficult, since it requires a trap on a different Tcl instruction, at which point my head starts to ache...
This command is incompatible with autoloading of procedures.
For users of Tcl 8.0, 8.1 and 8.2, this code provides a route for
executing commands that improves over the performance of the
eval
command by a substantial margin.
This script that implements the command ::fasteval::fasteval that is almost exactly like the standard Tcl eval except faster.
Note that the system does not handle comments or multiple commands correctly at all, and putting that support in would make the speedup trick used impossible.
The above techniques are no longer needed. From the
C level, you can call Tcl_EvalObjv()
and from the Tcl
level you can simply make sure that the arguments you pass to
eval
are pure lists (i.e. lists which have no string
interpretation.) Using these techniques have additional advantages
over particularly the C code above, in that autoloading and command
modification work, and all commands are supported. You can
force a list to be pure by using the lrange
command, like
this:
set pureList [lrange $dirtyList 0 end]
You should note that many lists are naturally pure anyway, but list-like literals are invariably not.
As a bonus, the concat
command works
much faster on pure lists too.