Posted to tcl by apn at Thu May 05 02:44:34 GMT 2022view pretty
I was surprised by the following (win) 1 % proc x {l e} {linsert $l 0 $e} (win) 2 % proc y {l args} {linsert $l 0 {*}$args} (win) 3 % set l {} ; time {set l [x $l a]} 50000 95.58538800000001 microseconds per iteration (win) 4 % set l {} ; time {set l [y $l a]} 50000 82.88127 microseconds per iteration Proc y is more than 10% faster despite the use of args and {*} Disassembling shows the difference (win) 5 % tcl::unsupported::disassemble proc x ByteCode 0x0000028C3E210D50, refCt 1, epoch 17, interp 0x0000028C3B79C620 (epoch 17) Source "linsert $l 0 $e" Cmds 1, src 15, inst 16, litObjs 0, aux 0, stkDepth 2, code/src 0.00 Proc 0x0000028C3E1D2D90, refCt 1, args 2, compiled locals 2 slot 0, scalar, arg, "l" slot 1, scalar, arg, "e" Commands 1: 1: pc 0-14, src 0-14 Command 1: "linsert $l 0 $e" (0) loadScalar1 %v0 # var "l" (2) loadScalar1 %v1 # var "e" (4) list 1 (9) reverse 2 (14) listConcat (15) done (win) 6 % tcl::unsupported::disassemble proc y ByteCode 0x0000028C3E211A50, refCt 1, epoch 17, interp 0x0000028C3B79C620 (epoch 17) Source "linsert $l 0 {*}$args" Cmds 1, src 21, inst 16, litObjs 2, aux 0, stkDepth 4, code/src 0.00 Proc 0x0000028C3E1C4E50, refCt 1, args 2, compiled locals 2 slot 0, scalar, arg, "l" slot 1, scalar, arg, "args" Commands 1: 1: pc 0-14, src 0-20 Command 1: "linsert $l 0 {*}$args" (0) expandStart (1) push1 0 # "linsert" (3) loadScalar1 %v0 # var "l" (5) push1 1 # "0" (7) loadScalar1 %v1 # var "args" (9) expandStkTop 4 (14) invokeExpanded (15) done If I understand that correctly, y invokes the C implemented Tcl_LinsertObjCmd while x does it all in byte code which is measurably slower.