2013-07-28 49 views
2

爲了比較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

我會使用'字符串範圍$ str 1 end-1'而不是字符串映射。另外,'if'條件已經是一個表達式,所以你只需要'if {$ i%3 == 0}'而不用調用expr。 –

+0

@glenn請注意'expr'是無支撐的... –

+0

嗨@唐納,我不明白你的評論。這不等於'[expr [expr $ i%3] == 0]'? –

回答

2

首先要做的事在程序(或lambda條款)儘可能多的代碼確保所有表達式都支持。那是你們兩個關鍵的問題,都是表現不佳。我們也會做一些其他的事情(在if測試中你幾乎不需要expr,這不是其中之一,string trimstring 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 

可能加入fconfigure $fp -encoding iso8859-1獲得更好的性能;你必須自己測試一下。但關鍵的變化是由於前面大膽的項目所致,因爲每個變化都會大大影響所用編譯策略的效率。 (另外,Tcl 8.5比8.6有點快 - 8.6有一個完全不同的執行引擎,對某些事情來說有點慢 - 所以你也可以用8.5來測試新代碼;代碼本身似乎對兩個版本都有效。 )

+0

謝謝你的回答! Tcl的人總是那麼棒! – mrsteve

1

嘗試使用regex {^[0-9,]+$} $line而不是checkListNat函數進行檢查。

更新 這裏有一個例子

回聲 「87566,45,67 \ n56,5r5,45」>!嘗試

...

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

給出:

> OK 87566,45,67

> BAD 56,5r5,45

+0

感謝您快速回答!真! – mrsteve