Reputation: 710
I've seen the theory and understand the explanation why the firsst is faster than the second, but I want to see the bytecode in tcl. in the python shell, it's pretty easy to see the bytecode, but I'm having trouble finding a solution to view this in tclsh.
#first approach
expr {3 * 4}
#second approach
expr 3 * 4
Any help would be appreciated.
Upvotes: 3
Views: 858
Reputation: 137627
To look at what bytecode Tcl has generated, use tcl::unsupported::disassemble
(assuming you've got Tcl 8.5 or later). Here's your examples:
% tcl::unsupported::disassemble script {expr {3 * 4}}
ByteCode 0x0x103058910, refCt 1, epoch 95, interp 0x0x100829a10 (epoch 95)
Source "expr {3 * 4}"
Cmds 1, src 12, inst 3, litObjs 1, aux 0, stkDepth 1, code/src 0.00
Commands 1:
1: pc 0-1, src 0-11
Command 1: "expr {3 * 4}"
(0) push1 0 # "12"
(2) done
% tcl::unsupported::disassemble script {expr 3 * 4}
ByteCode 0x0x1030b2f10, refCt 1, epoch 95, interp 0x0x100829a10 (epoch 95)
Source "expr 3 * 4"
Cmds 1, src 10, inst 14, litObjs 4, aux 0, stkDepth 5, code/src 0.00
Commands 1:
1: pc 0-12, src 0-9
Command 1: "expr 3 * 4"
(0) push1 0 # "3"
(2) push1 1 # " "
(4) push1 2 # "*"
(6) push1 1 # " "
(8) push1 3 # "4"
(10) concat1 5
(12) exprStk
(13) done
As you can see, in one case Tcl has found that it has a compile-time constant and used that, and in the other case it is building an expression and firing that into the runtime expression engine (via exprStk
, which I can tell you recursively invokes the compiler on what is in this case an entirely new object and so won't end up caching anything and will be expensive).
You can disassemble other things, notably proc
(for procedures), lambda
(for apply
terms), and method
(for TclOO methods; this one requires Tcl 8.6).
In Tcl 8.4 and earlier, it is possible to get the disassembler to print things out. You just set the global tcl_traceCompile
variable to 2
— provided the Tcl library was built with the right configuration options, --enable-symbols=all
is the most useful variant — and then force the code to be compiled; the disassembly (same format) gets printed straight to the real console. But this was an awful way to do it; 8.5 added the command version in all builds precisely to get away from that horrid mucking around with global variables. (There's also tcl_traceExec
…)
8.6.3 will have another disassembler too, which produces output suitable for further scripting.
Upvotes: 3