TCL全球与可变访问速度

时间:2016-09-27 16:35:51

标签: namespaces tcl global

在TCL中,粗略地说,有可以通过global varname访问的全局变量,或者可以通过namespace varname命令访问的命名空间变量。
我非常简单地检查2的访问时间对于版本tcl 8.5,variableglobal显示了微小且一致的运行时访问优势。
我们可以期待8.6及以上的情况,至少现在是这样吗?

1 个答案:

答案 0 :(得分:4)

tl; dr: 非常两者之间的速度差别不大,还不够你应该关心。以语义正确的方式做事并留在那里。正确用于您的用例将在时间方面击败任何修补百分比。

让我们比较全局命名空间中执行相同操作的以下两个过程。请注意,我们比较的选项之间的差异权重将相对于实际代码人为地提高;这些是微观基准,应该被怀疑地对待。

# Using the default `epsilon` of 0.001
assert_in_epsilon(1_000, actual[0])
assert_in_epsilon(1_000_000, actual[1])

好的,时间信息(您的绝对时间 会因硬件而异):

assert_in_delta(1_000, actual[0], 1)
assert_in_delta(1_000_000, actual[1], 1000)

是的,proc a {} { global x y expr {$x + $y} } proc b {} { variable x variable y expr {$x + $y} } 略慢于% set x 123 123 % set y 456 456 % a 579 % b 579 % time { a } 10000 0.5720533 microseconds per iteration % time { b } 10000 0.5756787999999999 microseconds per iteration 。让我们看看字节码,看看为什么:

b

您的Tcl版本中的确切字节码序列可能有所不同;这完全是实施的一部分,而不是官方界面。但是,我们可以看到,对于a,操作码序列涉及命名实现中的一个% tcl::unsupported::disassemble proc a ByteCode 0x0x10280fe10, refCt 1, epoch 15, interp 0x0x100829a10 (epoch 15) Source "\n global x y\n expr {$x + $y"... Cmds 2, src 35, inst 35, litObjs 4, aux 0, stkDepth 2, code/src 0.00 Proc 0x0x102822c10, refCt 1, args 0, compiled locals 2 slot 0, scalar, "x" slot 1, scalar, "y" Commands 2: 1: pc 0-19, src 5-14 2: pc 20-33, src 20-33 Command 1: "global x y"... (0) push1 0 # "::" (2) push1 1 # "x" (4) nsupvar %v0 # var "x" (9) push1 2 # "y" (11) nsupvar %v1 # var "y" (16) pop (17) nop (18) nop (19) nop Command 2: "expr {$x + $y}"... (20) startCommand +14 1 # next cmd at pc 34, 1 cmds start here (29) loadScalar1 %v0 # var "x" (31) loadScalar1 %v1 # var "y" (33) add (34) done % tcl::unsupported::disassemble proc b ByteCode 0x0x10280fa10, refCt 1, epoch 15, interp 0x0x100829a10 (epoch 15) Source "\n variable x\n variable y\n expr {$x + $"... Cmds 3, src 50, inst 44, litObjs 3, aux 0, stkDepth 2, code/src 0.00 Proc 0x0x102822a90, refCt 1, args 0, compiled locals 2 slot 0, scalar, "x" slot 1, scalar, "y" Commands 3: 1: pc 0-9, src 5-14 2: pc 10-28, src 20-29 3: pc 29-42, src 35-48 Command 1: "variable x"... (0) push1 0 # "x" (2) variable %v0 # var "x" (7) nop (8) nop (9) nop Command 2: "variable y"... (10) startCommand +18 1 # next cmd at pc 28, 1 cmds start here (19) push1 2 # "y" (21) variable %v1 # var "y" (26) push1 1 # "" (28) pop Command 3: "expr {$x + $y}"... (29) startCommand +14 1 # next cmd at pc 43, 1 cmds start here (38) loadScalar1 %v0 # var "x" (40) loadScalar1 %v1 # var "y" (42) add (43) done 命名空间句柄和两个global,以及两个push1调用时,不会推送命名空间,但nsupvar操作码使用两次,两者之间有一个额外的variablevariable是一个混乱的基础设施,其副作用是抑制一些小的优化,因此可能是原因。

如果两者之间存在这么小的差异,那么确定性能差异的地方就需要像cachegrind这样的工具......

BTW,尝试将性能与此进行比较:

startCommand

与上面的startCommand程序有完全相同的字节码序列...