Posted to tcl by apn at Thu May 05 02:44:34 GMT 2022view raw

  1. I was surprised by the following
  2. (win) 1 % proc x {l e} {linsert $l 0 $e}
  3. (win) 2 % proc y {l args} {linsert $l 0 {*}$args}
  4. (win) 3 % set l {} ; time {set l [x $l a]} 50000
  5. 95.58538800000001 microseconds per iteration
  6. (win) 4 % set l {} ; time {set l [y $l a]} 50000
  7. 82.88127 microseconds per iteration
  8. Proc y is more than 10% faster despite the use of args and {*}
  9. Disassembling shows the difference
  10. (win) 5 % tcl::unsupported::disassemble proc x
  11. ByteCode 0x0000028C3E210D50, refCt 1, epoch 17, interp 0x0000028C3B79C620 (epoch 17)
  12. Source "linsert $l 0 $e"
  13. Cmds 1, src 15, inst 16, litObjs 0, aux 0, stkDepth 2, code/src 0.00
  14. Proc 0x0000028C3E1D2D90, refCt 1, args 2, compiled locals 2
  15. slot 0, scalar, arg, "l"
  16. slot 1, scalar, arg, "e"
  17. Commands 1:
  18. 1: pc 0-14, src 0-14
  19. Command 1: "linsert $l 0 $e"
  20. (0) loadScalar1 %v0 # var "l"
  21. (2) loadScalar1 %v1 # var "e"
  22. (4) list 1
  23. (9) reverse 2
  24. (14) listConcat
  25. (15) done
  26. (win) 6 % tcl::unsupported::disassemble proc y
  27. ByteCode 0x0000028C3E211A50, refCt 1, epoch 17, interp 0x0000028C3B79C620 (epoch 17)
  28. Source "linsert $l 0 {*}$args"
  29. Cmds 1, src 21, inst 16, litObjs 2, aux 0, stkDepth 4, code/src 0.00
  30. Proc 0x0000028C3E1C4E50, refCt 1, args 2, compiled locals 2
  31. slot 0, scalar, arg, "l"
  32. slot 1, scalar, arg, "args"
  33. Commands 1:
  34. 1: pc 0-14, src 0-20
  35. Command 1: "linsert $l 0 {*}$args"
  36. (0) expandStart
  37. (1) push1 0 # "linsert"
  38. (3) loadScalar1 %v0 # var "l"
  39. (5) push1 1 # "0"
  40. (7) loadScalar1 %v1 # var "args"
  41. (9) expandStkTop 4
  42. (14) invokeExpanded
  43. (15) done
  44. If I understand that correctly, y invokes the C implemented Tcl_LinsertObjCmd while x does it all in byte code which is measurably slower.

AltStyle によって変換されたページ (->オリジナル) /