【发布时间】:2015-10-05 14:27:17
【问题描述】:
我有一个由许多 tcl 文件和过程组成的 tcl 环境,它们都在同一个命名空间下。开发了其中一个过程,以便它根据输入参数递归地调用自身。概要是:
myproc *subcmd arg1*
在哪里:
- subcmd 是一个子命令
- arg1 是一个寄存器
arg1 可能是一个普通寄存器或 all 寄存器,它导致将 subcmd 子命令提交给所有允许的寄存器。报告子命令是 get_status/get_delta/get_mask,最坏的情况由 get_value 子命令表示,该子命令依次调用前一个子命令。如果提供了寄存器all,则过程级堆栈如下:
myproc get_value all
myproc get_value reg1
myproc get_status reg1
myproc get_delta reg1
myproc get_mask reg1
myproc get_value reg2
myproc get_status reg2
myproc get_delta reg2
myproc get_mask reg2
...
myproc get_value reg(n-1)
myproc get_status reg(n-1)
myproc get_delta reg(n-1)
myproc get_mask reg(n-1)
myproc get_value reg(n)
myproc get_status reg(n)
myproc get_delta reg(n)
myproc get_mask reg(n)
这样我可以缓慢执行最底层的执行。 我尝试在互联网上浏览以获取有关如何在没有结果的情况下提高性能的信息。一个可能的解决方案似乎是 apply 命令(lambda 函数的父级),但我想这对我的目的来说太简单了,其他方法可能会满足我的问题。有什么建议吗?
此刻我用内部语句回忆了过程本身:
eval {myproc *subcmd* arg1}
编辑日志和附加信息
我已经修改了代码,使跟踪忠实于真实的。此外,我发布了一些源代码片段,以便您了解如何有效地调用这些过程:
# this is the call statement for 'all' register.
# exp_opt1_list holds reg1, reg2, ..., reg(n)
# the other parameter are not worth to explain, they are parsed above
# *callprocname* is a procedure that return back the name of the call procedure which reside 1 level above. Practically this procedure is shared by identical procedures at upper level which differ only for the lists of registers. So callprocname gives the name of the upper procedure that originally called that core procedure
foreach opt1_scan $exp_opt1_list($sub_cmd) {
if {($opt1 == "all") && $opt1_scan != "all" } {
set scan_result_list [string tolower [callprocname]] $sub_cmd $tag1 $tag2 $tag3 $opt1_scan $local_verbose -loop]
[...]
}
}
后续 get_* 所在的行如下(加上一个清除寄存器的 clear_delta):
if {[string equal -nocase GET_VALUE $sub_cmd]} {
set result [list]
lappend result [eval [list [string tolower [callprocname]] get_status $tag1 $tag2 $tag3 $opt1 $local_verbose]]
lappend result [eval [list [string tolower [callprocname]] get_delta $tag1 $tag2 $tag3 $opt1 $local_verbose]]
eval [list [string tolower [callprocname]] clr_delta $tag1 $tag2 $tag3 $opt1 $operation_verbose]
lappend result [eval [list [string tolower [callprocname]] get_mask $tag1 $tag2 $tag3 $opt1 $local_verbose]]
}
作为第一个代码主干状态中的注释,有许多嵌套过程,尽管它们大多数都是微不足道的,或者换句话说,对计算的要求不高。事实上,这个结构涉及到很多层级,比如说6层(服务+核心),因为一切都是从调用核心的服务层开始的,如果涉及到all寄存器再次直接从核心调用服务级别,所以我们有 service -> core -> service -> core 等等。
这样粗略的解释就足够了吗?
【问题讨论】:
-
嗯,eval 真的很慢。为什么不正常运行该过程:
myproc *subcmd* arg1 -
另外,向我们展示真实代码比伪代码更有用。
-
调用 lambda 也不会加快速度,但您所描述的调用结构不应该明显慢:可能还有其他因素导致它执行缓慢。使用真正的 ensemble 命令而不是设置即兴的 ensemble 界面可能会清除一些问题。
-
实际上我尝试使用 eval 只是因为我认为提供类似“eval {[list myproc arg1 arg2]}”的东西更快。内部调用与您一开始的“正常”定义相同,但同样缓慢。我无法显示整个代码,因为它有两千行。
-
使用
time命令和[clock milliseconds]的标准调试来找出速度问题的确切位置可能很有用。
标签: performance recursion tcl