加速Tcl评估 [英] accelerate Tcl eval
问题描述
我目前正在编写一个基于Tcl的工具,用于符号矩阵操作,但是代码变慢了。我正在寻找加速我的Tcl代码(Tcl版本8.6)的方法。
我有一个怀疑。我的代码构建的列表将命令名作为第一个元素,将命令参数作为以下元素(这来自于模拟面向对象的方法)。我使用eval
调用这些命令(在递归处理中经常这样做)。我在https://wiki.tcl-lang.org/page/eval和https://wiki.tcl-lang.org/page/Tcl+Performance看到eval
可能很慢。
我有三个问题:
从包含刚才构造的命令名称和参数的列表中调用命令的最快方式是什么?
将命令名
myCmd
和参数列表myPar
分开,并改为使用[$myCmd {*}$myPar]
调用命令(建议在https://stackoverflow.com/a/27619692/3852630处),是否会加速代码?使用
if 1
而不是eval
的技巧在8.6中仍然有希望吗?
非常感谢您的帮助!
推荐答案
最重要的是,不要想当然地假定:time
。请注意,在对重复运行某项内容可能进行计时时,可能会更改其运行所需的时间(因为缓存预热)。仔细考虑您要实际获得的速度。
eval
命令通常很慢,但并非在所有情况下都是如此。如果您给它一个您构造的列表(例如,使用list
、linsert
、lappend
或…)那么它就相当快了,因为它可以避免重新解析输入;它知道(但只有在这种情况下)它可以直接跳到分派到命令实现。另一种快速的情况是,当您为它赋予一个以前赋予eval
的值时;字节码已经构建并缓存。这些注释也适用于uplevel
。
执行$myCmd {*}$myParameters
也相当快;它被字节编码为"在Tcl操作数堆栈上汇编字词并进行正确的命令调度",这非常接近于任意用户命令(很少有直接字节码实现)。
我预计if 1
在某些情况下会非常快,在其他情况下会非常慢;它会强制进行完全编译,所以如果可以很好地缓存,那么就会很快,如果不能,就会很慢。如果您只是在调用一个命令,那么充其量也不会有太大的不同。当被调用的对象本身是一个字节编码的命令和时,它会获胜,此时您可以正确地缓存内容。
如果您处理的是普通命令(例如,过程或Tcl的某个触及操作系统的命令),我会选择选项2:或其变体。这差不多是你能拿到的最快速度了。但我不会这么做:
set myParameters [linsert $myOriginalValues 0 "literal1" [cmdOutput2] $value3]
$myCmd {*}$myParameters
那太荒谬了。这更清晰、更干净、更快捷:
$myCmd "literal1" [cmdOutput2] $value3 {*}$myOriginalValues
扩展语法({*}
)的一部分是您不需要进行复杂的参数编组,这很好,因为复杂性很难一直正确。
这篇关于加速Tcl评估的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!