Tcl upvar 和性能提升
Tcl upvar and uplevel in performance
假设我有一个上一级的变量,我只想查询它的值。我有两个选择:
uplevel { set var_name }
或者:
upvar var_name
如果我只需要查询一次变量而不更改它,哪个应该更快?
您会发现 upvar
可能更快。不一定,但很有可能。 (如果您担心性能,time
其他选择。)
请注意,它们都必须解析变量名;这是无论如何都要承担的成本。但是带有 upvar
的版本不涉及在上下文之间移动代码,因此它可能会更快。
FWIW,当我尝试使用下面的示例时,我的直觉是正确的。 (关键是一个使用 upvar
字节码操作码;另一个使用 invokeStk
,后者速度较慢,因为它是通用命令调度程序,并且有大量用于其他目的所需的开销。)
% proc foo {y} {set x 1; bar $y}
% proc bar {y} {upvar 1 x x; list $x $y}
% foo 2
1 2
% time {foo 2} 10000
17.8188412 microseconds per iteration
% proc bar {y} {set x [uplevel 1 {set x}]; list $x $y}
% foo 2
1 2
% time {foo 2} 10000
25.4614022 microseconds per iteration
对于这种微基准测试,我更喜欢 timerate
:
% namespace import ::tcl::unsupported::timerate
% timerate -calibrate {}
0.03257451263357219 µs/#-overhead 0.032807 µs/# 59499506 # 30481304 #/sec
% proc foo {y} {set x 1; bar $y}
% proc bar {y} {upvar 1 x x; list $x $y}
% timerate {foo 2} 10000
0.437240 µs/# 21285016 # 2287075 #/sec 9306.651 net-ms
% proc bar {y} {set x [uplevel 1 {set x}]; list $x $y}
% timerate {foo 2} 10000
0.612693 µs/# 15497439 # 1632137 #/sec 9495.179 net-ms
(答案很明确:使用upvar
)。
假设我有一个上一级的变量,我只想查询它的值。我有两个选择:
uplevel { set var_name }
或者:
upvar var_name
如果我只需要查询一次变量而不更改它,哪个应该更快?
您会发现 upvar
可能更快。不一定,但很有可能。 (如果您担心性能,time
其他选择。)
请注意,它们都必须解析变量名;这是无论如何都要承担的成本。但是带有 upvar
的版本不涉及在上下文之间移动代码,因此它可能会更快。
FWIW,当我尝试使用下面的示例时,我的直觉是正确的。 (关键是一个使用 upvar
字节码操作码;另一个使用 invokeStk
,后者速度较慢,因为它是通用命令调度程序,并且有大量用于其他目的所需的开销。)
% proc foo {y} {set x 1; bar $y}
% proc bar {y} {upvar 1 x x; list $x $y}
% foo 2
1 2
% time {foo 2} 10000
17.8188412 microseconds per iteration
% proc bar {y} {set x [uplevel 1 {set x}]; list $x $y}
% foo 2
1 2
% time {foo 2} 10000
25.4614022 microseconds per iteration
对于这种微基准测试,我更喜欢 timerate
:
% namespace import ::tcl::unsupported::timerate
% timerate -calibrate {}
0.03257451263357219 µs/#-overhead 0.032807 µs/# 59499506 # 30481304 #/sec
% proc foo {y} {set x 1; bar $y}
% proc bar {y} {upvar 1 x x; list $x $y}
% timerate {foo 2} 10000
0.437240 µs/# 21285016 # 2287075 #/sec 9306.651 net-ms
% proc bar {y} {set x [uplevel 1 {set x}]; list $x $y}
% timerate {foo 2} 10000
0.612693 µs/# 15497439 # 1632137 #/sec 9495.179 net-ms
(答案很明确:使用upvar
)。