5 ms·
"everything is a string" hasn't been a serious performance issue since the release of Tcl 8.0 decades ago. I've written large, successful applications in Tcl/T
by wduquette 2y ago
"everything is a string" hasn't been a serious performance issue since the release of Tcl 8.0 decades ago. I've written large, successful applications in Tcl/Tk.
Granted, programming in the large in Tcl requires discipline and a good set of tools. (I used the Snit object framework, with SQLite as a data store.)
As for command languages: yes, this is where Tcl really shines; nothing else is as good.
- kragen 2y agotcl 8.6.13 still has serious performance problems, although indeed 8.0 did improve the situation dramatically; it's on the order of 64× slower than native code in simple microbenchmarks like http://canonical.org/~kragen/sw/dev3/dumbfib.tcl http://canonical.org/~kragen/sw/dev3/dumbfib.tcl, which also means about 2× slower than cpython. its type system is a big part of the reason why compare†: : ~; time tclsh <<<'proc fib {n} { if {$n < 2} {return 1} else {return [expr {[fib [expr {$n - 1}]] + [fib [expr {$n - 2}]]}]}}; puts [fib 35]' 14930352 real 0m8.351s user 0m8.346s sys 0m0.004s : ~; time luajit -e 'function fib(n) if n < 2 then return 1 else return fib(n-1) + fib(n-2) end end print(fib(35))' 14930352 real 0m0.127s user 0m0.122s sys 0m0.004s even with the huge performance hacks added in tcl 8.0, it's only about 64 times faster than bash : ~; time bash -c 'fib() { if [[ $1 -lt 2 ]]; then result=1; else local arg=$1; fib $(($arg - 1)); local tmp=$result; fib $(($arg - 2)); result=$(($tmp + $result)); fi; }; fib 35; echo "$result"' 14930352 real 8m24.591s user 8m24.412s sys 0m0.028s which puts it about halfway in between shell scripts and native code that doesn't mean you can't write large, successful applications in tcl, even without any c extensions! a core i7 is about 17000 dhrystone vax mips http://www.roylongbottom.org.uk/dhrystone%20results.htm http://www.roylongbottom.org.uk/dhrystone%20results.htm while a pentium 166 was about 270 mips. so anything you could do with usable performance on a pentium you can do, with enough discipline, in pure tcl. it'll probably be a lot quicker to write than pentium assembly, too. and things like arrays (hash tables), regular expressions, sqlite, tk, etc., are of course enormously faster on a current computer, and you have a thousand times as much ram to play with and probably an ssd but you probably don't want to write your fractal renderer or real-time raytracer in tcl. by contrast, i've done both of those successfully in lua with luajit: https://gitlab.com/kragen/bubbleos/blob/master/yeso/mand.lua https://gitlab.com/kragen/bubbleos/blob/master/yeso/mand.lua https://gitlab.com/kragen/bubbleos/-/blob/master/yeso/sdf.lua https://gitlab.com/kragen/bubbleos/-/blob/master/yeso/sdf.lu... in terms of command languages, what do you recommend for getting good tab-completion in tcl? i don't know of any good options but that doesn't mean there aren't any; it probably just means i'm ignorant ______ †before wduquette's very helpful correction, I had: : ~; time tclsh <<<'proc fib {n} { if {$n < 2} {return 1} else {return [expr [fib [expr $n - 1]] + [fib [expr $n - 2]]]}}; puts [fib 35]' 14930352 real 0m59.757s user 0m59.736s sys 0m0.004s and while, in some sense, maybe my additional 8× slowdown here was kind of a performance effect of the everything-is-a-string type system, it's not an unavoidable one
- wduquette 2y agoYou can speed that Tcl snippet up considerably by putting braces around the expressions, e.g., `expr {$n - 1}`. On my system it went from ~22 seconds to ~4 seconds. Without the braces, the expression gets parsed twice, once as Tcl syntax and once as Tcl `expr` syntax. Luajit is still going to be faster, but Tcl will do better than what you're showing there. (Not bracing expressions is the most common reason by why Tcl code runs slowly.) In terms of tab-completion, you have to roll your own; and if you're trying to do it in the console, you're going to need to write your own REPL: the standard `tclsh` doesn't even have "readline" editing. Back when I was doing Tcl regularly, I wrote a Tk "terminal" widget, and all my Tcl/Tk apps had a way to pop it up. Made life much easier.
- kragen 2y agohey, thanks! i should have known that and didn't. i've corrected my comment above since you corrected me so quickly that i could still edit it! i feel like readline and tab-completion is pretty important to a good command language, and plausibly you want to integrate support for tab-completion into the design of the language itself rather than having to write a separate completer for each command i'm kind of puzzled why tclsh doesn't have any command-line editing. maybe ousterhout's team was only ever using tclsh in emacs shell-mode or something like your tk terminal? as an exercise, i wrote a basic command-line editor in c in bed on my cellphone the other night. it took me an hour and a half and 120 lines of code (with a very narrow line length to fit onto the cellphone screen), and it supports arrow keys, movement by words, word delete, about a dozen keystroke commands in all, which is most of the ones i use. (though i really need to fix the cbreak handling and handling of wide lines to work reliably.) http://canonical.org/~kragen/sw/dev3/editline.c http://canonical.org/~kragen/sw/dev3/editline.c tcl is about 200'000 lines of c; there's no reason for tclsh to be missing this
- wduquette 2y agoHistorically it’s because TCL uses the BSD license and GNU readline does not. But yeah, no reason not to implement an alternative. As for speed, it’s less that everything is a string (internally, data gets stored as both a string and whatever it last needed to be converted to) and more because TCL is so dynamic that compiling it is hard. There’s been some work on compiling to native though.