2015-10-05 64 views
1

我有一个由许多tcl文件和过程组成的tcl环境,它们都在同一个命名空间下。根据输入参数递归地开发该过程之一。 Synopsys的是:TCL中的递归过程调用

myproc *subcmd arg1* 

其中:

  • subcmd是一个子命令
  • ARG1是寄存器

ARG1可以是正常寄存器或所有注册会导致提交子命令子命令给整体允许的注册者。报告子命令为get_status/get_delta/get_mask,最坏的情况由get_value子命令表示,该子命令继承前面的子命令。如果提供寄存器所有,程序级堆栈如下:

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层(服务+核心),因为一切都从调用核心的服务级别开始,如果涉及到注册,那么调用服务级别再次直接从核心,所以我们有服务 - >核心 - >服务 - >核心等等。

这个粗略的解释是否足够?

+0

恩,eval真的很慢。为什么不像普通程序那样运行程序:'myproc * subcmd * arg1' –

+0

另外,向我们展示真正的代码比伪代码更有用。 –

+1

调用lambda并不会加快速度,但是您所描述的调用结构的类型不应该明显变慢:可能还有其他一些因素导致其执行缓慢。使用真正的合奏命令而不是设置即兴合奏界面可能会清除一些事情。 –

回答

0

你几乎猜到了我的代码是如何工作的,但我修改它以使它更接近我的代码。


你的代码看起来像这样吗?

proc myproc {subcmd reg} { 
    set n 5 
    switch -- $subcmd { 
     get_value { 
      if {$reg eq "all"} { 
       for {set i 1} {$i < $n} {incr i} { 
        myproc get_status reg$i 
        myproc get_delta reg$i 
        myproc get_mask reg$i 
       } 
      } 
     } 
     get_status { 
      if {$reg eq "all"} { 
       for {set i 1} {$i < $n} {incr i} { 
        myproc get_status reg$i 
       } 
      } else { 
       # do what get_status does with a single register 
      } 
     } 
     get_delta { 
      if {$reg eq "all"} { 
       for {set i 1} {$i < $n} {incr i} { 
        myproc get_delta reg$i 
       } 
      } else { 
       # do what get_delta does with a single register 
      } 
     } 
     get_mask { 
      if {$reg eq "all"} { 
       for {set i 1} {$i < $n} {incr i} { 
        myproc get_mask reg$i 
       } 
      } else { 
       # do what get_mask does with a single register 
      } 
     } 
    } 
} 

我在问,因为我们真的需要弄清楚你的代码是什么样子才能提醒你。

调用跟踪上面的代码:

myproc get_value all 
    myproc get_status reg1 
    myproc get_delta reg1 
    myproc get_mask reg1 
    myproc get_status reg2 
    myproc get_delta reg2 
    myproc get_mask reg2 
    myproc get_status reg3 
    myproc get_delta reg3 
    myproc get_mask reg3 
    myproc get_status reg4 
    myproc get_delta reg4 
    myproc get_mask reg4 

BTW我试图“档案”我的代码以[时间],它只是似乎它缓慢归因于对嵌套来电...

+0

我编辑了代码,使其与我的类似... – MFrancone

+0

@MFrancone:好的,只有这个代码并不真正与您的问题中的模拟呼叫跟踪押韵。我添加了更新的通话跟踪。 –