tcl 非花括号表达式比用它们慢?

tcl non curly braces expression slower than with them?

我注意到了一些事情。让我们看看两个代码位。在1中,如果不是用花括号输入,另一个是。大括号 1 稍快一些。为什么?
请参阅下面的代码和输出:

puts [ time { if { [ expr { 5 % 2 } ] } { puts 1 } else { puts 2 } } ]
1
52 microseconds per iteration
puts [ time { if [ expr { 5 % 2 } ] { puts 1 } else { puts 2 } } ]
1
54 microseconds per iteration

差异稳定。使用更多代码字符时快 2 微秒。
为什么?

就像 expr 一样,支持 ifexpr 使您的代码 faster/more 高效。基本上,没有大括号,我引用上面的 wiki link,expr 可能会经历意外的转换 numeric -> string -> numeric,你可能会失去精度,你的表达式将是慢得多,你甚至会遇到安全问题。

引用 a different wiki:

Question: Does the evaluation of expr1 by if differ from how expr evaluates its arguments?

Answer: No, expr in if is processed exactly the same as an argument to expr

DKF: They use the same parser and bytecode generator. Main difference is that expr concatenates its arguments before parsing, but if requires a single argument.

定时一次不是很有用:让它 运行 10000 次

将命令放入过程中:(删除内部 puts 命令以消除嘈杂的输出)

proc time_it {n} {
  # bracing the command
  puts [time {if {[expr {5%2}]} {expr 1} else {expr 2}} $n]
  # unbraced
  puts [time {if [expr {5%2}] {expr 1} else {expr 2}} $n]
  # removing the unnecessary `expr` command altogether
  puts [time {if {5%2} {expr 1} else {expr 2}} $n]
}

然后,运行一次,两次

% time_it 1
89 microseconds per iteration
27 microseconds per iteration
45 microseconds per iteration
% time_it 1
3 microseconds per iteration
8 microseconds per iteration
1 microseconds per iteration

我假设在第一个 运行 期间正在进行一些编译。在第 2 个 运行 期间,非支撑代码最慢。现在,在一系列迭代中计时。

% time_it 1000
0.27 microseconds per iteration
1.245 microseconds per iteration
0.267 microseconds per iteration
% time_it 10000
0.2823 microseconds per iteration
1.2491 microseconds per iteration
0.2198 microseconds per iteration
% time_it 100000
0.28989 microseconds per iteration
0.80064 microseconds per iteration
0.11543 microseconds per iteration

当你用大括号括起一个表达式时,尤其是当你在该表达式中使用可变部分时,Tcl 变得能够​​在脚本编译时确定表达式的语义是什么。这允许它为表达式生成字节码,并在实际 运行 编码代码时使一切变得更加快速。

如果没有大括号,编译器可能不得不回退到只发出编译指令和运行 运行 时的表达式。也就是说,它基本上推迟了真正的编译工作。显然,这并没有那么快,因为分析事物 永远不会 是免费的。 (它也可能有其他问题,例如允许安全问题。)

在您的具体示例中,差异不是很大。对于真实的脚本,如果您使用正确的大括号,它可以 轻松地 将它们 运行 的速度提高一倍或三倍。更快and更安全and还好写吗?有什么不喜欢的!