我正在执行一个微小的速度测试,以便比较Agda programming language与Tcl脚本语言的速度。它用于科学工作,这只是一个预测试,而不是一个真正的测试。我无论如何都试图进行真实的速度比较!
我想出了一个小例子,其中Agda比Tcl快10倍。我使用这个例子有特殊原因。我主要担心的是我的Tcl代码编程错误,这是Tcl在这个例子中比Agda慢的唯一原因。
代码的目标是解析表示整数列表的行,并检查它是否确实是整数列表。
示例“(1,2,3)
”将是有效列表
示例“(1,a,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之间的速度测试更加真实?
答案 0 :(得分:2)
要做的第一件事是在程序中添加尽可能多的代码(或lambda术语)尽可能和确保所有表达式都被支撑。这是你的两个关键问题,即杀死性能。我们还会做其他一些事情(在expr
测试中你几乎不需要if
而这不是其中一种情况,string trim
比{{1}更合适},string map
确实应该用string 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
,您可能获得更好的效果;你必须自己测试一下。但关键的变化是由于之前的大胆项目所致,因为每个项目都会大大影响所使用的编译策略的效率。 (另外,Tcl 8.5比8.6快一点 - 8.6有一个截然不同的执行引擎,对某些东西来说有点慢 - 所以你也可以用8.5测试新代码;代码本身似乎对两个版本都有效。 )
答案 1 :(得分:1)
尝试使用regex {^[0-9,]+$} $line
代替checkListNat
函数进行核对。
<强>更新强> 这是一个例子
回声“87,566,45,67 \ n56,5r5,45”&gt;!尝试
...
while {[gets $fp line] >0} {
if {[regexp {^[0-9]+$} $line] >0 } {
puts "OK $line"
} else {
puts "BAD $line"
}
}
给出:
&gt; OK 87,566,45,67
&gt; BAD 56,5r5,45