2017-06-19 37 views
1

这是一个普遍的问题的东西。假设TCL 8.6,让我们来看看我有一个相当短的程序。我有2种方法返回所关心的价值:
1.使用一些标准做法的if/else代码,存储在一个变量,并返回变量的值。例如:
吹毛求疵:TCL存放在变量与否,对于速度,程序

proc me { gop goo } { 
    if { [ lomsa $gop ] { 
     set ret [ foo $goo $gop ] 
    } else { 
     set ret [ bar $gop $goo ] 
    } 
    return $ret 
} 

2.使用三元参数,并且基本上,具有程序不添加专用变量(即,仅使用参数)。三元表达式的输出是返回值。例如:

proc me { gop goo } { 
    expr { [ lomsa $gop ] ? [ foo $goo $gop ] : [ bar $gop $goo ] } 
} 

可读性是由我的团队的一些成员认为是更好的项目稍好1.
我无法访问的伪代码引擎在我的TCL设置(这是从一个shell一个供应商),但我认为代码中的差异,以及它的性能会是,但只是轻微的,如果有的话。即,程序需要存储返回值的某个地方。注册一个特定变量的成本是多少,而不仅仅是将其作为一个返回值?
这个问题可以扩展,例如,switch语句。相同的规则适用。 switch语句可以在一个变量存储,然后,在开关后,将返回变量的值,或switch语句将只返回值,W/O将其存储在一个变量。另外,在返回部分之前可以有大量的代码。上述程序上市是他们所谓的“方便过程”
你可以认为性能是代码的高利息。

回答

1

除了可读性,三元运营商可能会产生意想不到的效果。例如,如果所选的proc返回0123,则您的me proc将返回83。所以除非你确定这种情况永远不会发生,否则使用if命令会更安全。

+0

哇!我需要开一个新的问题来理解为什么会发生这种情况。 – user1134991

1

编译成字节码,命令两个版本都没有很大的不同:在两种情况下,选择结构被转换为分支指令。

要大致看看你的代码将是什么样子编译并准备运行,使用tcl::unsupported::disassemble proc <name-of-proc>。一些注意事项:该命令不受支持,这意味着它不能保证按照您期望的方式工作,或保持现在在将来版本中的工作方式。除非您非常熟悉字节码解释器的工作方式,否则查看反汇编列表也可能会让人误以为您可能会想到。

要了解有关性能的更多信息,您应该查看time命令和bench程序包,这些程序包对于衡量性能非常有用。

文档: bench (package)time

+0

我知道使用时间。我对引擎盖下的东西感兴趣。更深入的了解... – user1134991

+0

@ user1134991:你是否也熟悉'tcl :: unsupported :: disassemble'? –

0

怎么样的中间立场?

proc me { gop goo } { 
    if { [lomsa $gop] } { 
     foo $goo $gop 
    } else { 
     bar $gop $goo 
    } 
} 

,或者如果你喜欢一个明确的回报:

proc me { gop goo } { 
    if { [lomsa $gop] } { 
     return [foo $goo $gop] 
    } else { 
     return [bar $gop $goo] 
    } 
} 
+0

最后一个因为参数应该按不同的顺序而中断。 –

+0

的确,我错过了。他们看起来太相似了。 –

2

有疑问时,不要猜测; time吧!

为了您的示例代码,在性能上的差异为lomsafoobar最琐碎的实现几个百分点之内,我可以逃脱(在其下方有在一些细微的技术差别的理解少数边缘情况)。对于任何更复杂的,你下来,你正在平衡局部变量的成本噪音访问与额外调用该值转换为可能的话数值的操作码,以及究竟是慢有“这取决于”领土。

switch声明,当它处理它可以编译在所有的情况下,使用Tcl的计算堆栈作为临时存储。是我再次写字节码编译,我可能会使用一个临时的局部变量(他们是无名的,你不能触摸它们从你的代码),从而保持其他一些计算更简单。要知道哪个是最快的选项,请记下您的实际代码;对一些不太复杂的代理代码进行计时可能会轻易得出相反的结论

在未来,差异应该变得较次。我们正在努力编译有效的本地代码。我们开发的编译策略几乎可以消除你在上面看到的实际代码生成之前所看到的差异。