解析整数列表(速度测试所需的优化)

时间:2013-07-28 13:39:35

标签: performance parsing tcl

我正在执行一个微小的速度测试,以便比较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之间的速度测试更加真实?

2 个答案:

答案 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