2

为了比较Agda 编程语言和 Tcl 脚本语言的速度,我正在执行一个微小的速度测试。它用于科学工作,这只是一个预测试,而不是真正的测试。无论如何,我并不是在尝试进行现实的速度比较!

我提出了一个小例子,其中 Agda 比 Tcl 快 10 倍。我使用这个例子有特殊的原因。我主要担心的是我的 Tcl 代码编程很糟糕,这是在这个例子中 Tcl 比 Agda 慢的唯一原因。

代码的目标是解析表示整数列表的行并检查它是否确实是整数列表。
示例“ (1,2,3)”将是一个有效列表。
示例“ (1,a,3)”不是有效列表。

我的输入是一个文件,我每隔三行(第 3 行)检查一次文件。如果任何一行不是整数列表,程序将打印“ false”。

我的输入文件:

(613424,505980,317647,870930,75580,897160,716297,668539,689646,196362,533020)


(727375,472272,22435,869407,320468,80779,302881,240382,196077,635360,568517)


(613424,505980,317647,870930,75580,897160,716297,668539,689646,196362,533020)

(但是,我的真实测试文件大约 3 兆字节大)

我目前解决这个问题的 Tcl 代码是:

package require Tcl 8.6

proc checkListNat {str} {
    set list [split [string map {"(" "" ")" ""} $str] ","]
    foreach l $list {
        if {[string is integer $l] == 0} {
            return 0
        }
    }
    return 1
}

set i 1
set fp [open "/tmp/test.txt" r]
while { [gets $fp data] >= 0 } {
    incr i 
    if { [expr $i % 3] == 0} {
        if { [checkListNat $data] == 0 } {
            puts "error"
        }
    }
}
close $fp

如何优化我当前的 Tcl 代码,让 Agda 和 Tcl 之间的速度测试更真实?

4

2 回答 2

2

首先要做的是在过程(或 lambda 术语)放入尽可能多的代码,确保所有表达式都用括号括起来。那是你影响性能的两个关键问题。我们还会做一些其他的事情(你几乎不需要在测试中,这不是其中一种情况,比 更合适,真的应该用 来完成)。有了这些,我得到了这个版本,它与你已经拥有的版本相对相似,但性能应该更高。exprifstring trimstring mapstring is-strict

package require Tcl 8.6

proc checkListNat {str} {
    foreach l [split [string trim $str "()"] ","] {
        if {[string is integer -strict $l] == 0} {
            return 0
        }
    }
    return 1
}

apply {{} {
    set i 1
    set fp [open "/tmp/test.txt" r]
    while { [gets $fp data] >= 0 } {
        if {[incr i] % 3 == 0 && ![checkListNat $data]} {
            puts "error"
        }
    }
    close $fp
}} {*}$argv

通过添加;您可能会获得更好的性能 fconfigure $fp -encoding iso8859-1你必须自己测试一下。但关键的变化是由于前面的粗体项目造成的,因为每个项目都会对所使用的编译策略的效率产生重大影响。(另外,Tcl 8.5 比 8.6 快一点——8.6 有一个完全不同的执行引擎,它在某些方面有点慢——所以你也可以用 8.5 测试新代码;代码本身似乎对两个版本都有效。 )

于 2013-07-28T15:16:48.617 回答
1

尝试检查regex {^[0-9,]+$} $line而不是checkListNat函数。

更新 这里是一个例子

回声 "87,566, 45,67\n56,5r5,45" >! 尝试

...

while {[gets $fp line] >0} {
 if {[regexp {^[0-9]+$} $line] >0 } {
  puts "OK $line"
 } else {
  puts "BAD $line"
 }
}

给出:

>好的 87,566, 45,67

>坏 56,5r5,45

于 2013-07-28T13:45:38.150 回答