out."/> out.">
為什麼 Go 中讀寫檔案比 Perl 慢很多?這是很多開發者在使用這兩種程式語言時常遇到的問題。在這篇文章中,php小編草莓將為您解答這個問題。在比較 Go 和 Perl 讀寫檔案的速度時,我們需要考慮到兩個關鍵因素:語言特性和底層實作。 Go 語言在檔案讀寫方面的設計理念與 Perl 不同,這導致了它們在效能上的差異。同時,底層實現也是影響讀寫速度的重要因素。接下來,我們將詳細分析這些因素,幫助您更好地理解為什麼 Go 中讀寫檔案比 Perl 慢得多。
我使用go是為了提高程式碼效率,但當我使用go讀寫檔案時,發現它的讀寫效率沒有perl高。是我代碼的問題還是其他原因?
建立輸入檔:
# input file: for i in $(seq 1 600000) do echo server$((random%800+100)),$random,$random,$random >> sample.csv done
用perl讀寫檔:
time cat sample.csv | perl -ne 'chomp;print"$_"' > out.txt
real 0m0.249s user 0m0.083s sys 0m0.049s
使用 go 讀寫檔:
package main import ( "bufio" "fmt" "io" "os" "strings" ) func main() { filepath := "./sample.csv" file, err := os.openfile(filepath, os.o_rdwr, 0666) if err != nil { fmt.println("open file error!", err) return } defer file.close() buf := bufio.newreader(file) for { line, err := buf.readstring('\n') line = strings.trimspace(line) fmt.println(line) if err != nil { if err == io.eof { fmt.println("file read ok!") break } else { fmt.println("read file error!", err) return } } } }
然後我運行:
time go run read.go > out.txt
real 0m2.332s user 0m0.326s sys 0m2.038s
為什麼 go 的讀寫速度比 perl 慢近 10 倍?
您正在將蘋果與橘子進行比較。
至少有兩個方法錯誤:
您的perl 咒語測量cat
如何讀取檔案並透過pipe(2) 發送其內容
,而perl
從那裡讀取數據,對其進行處理並將結果寫入其標準輸出。
你的圍棋咒語
fmt.print*
呼叫),而在perl 程式碼中寫入標準輸出- 引用文件 - 「如果輸出到終端,通常可以進行行緩衝,否則進行區塊緩衝。」
#讓我們試著比較一下蘋果。
首先,這是一個類似的 go 實作:
package main import ( "bufio" "bytes" "fmt" "os" ) func main() { in := bufio.newscanner(os.stdin) out := bufio.newwriter(os.stdout) for in.scan() { s := bytes.trimspace(in.bytes()) if _, err := out.write(s); err != nil { fmt.fprint(os.stderr, "failed to write file:", err) os.exit(1) } } if err := out.flush(); err != nil { fmt.fprint(os.stderr, "failed to write file:", err) os.exit(1) } if err := in.err(); err != nil { fmt.fprint(os.stderr, "reading failed:", err) os.exit(1) } }
讓我們將其儲存為 chomp.go
並進行測量:
建構程式碼:
$ go build chomp.go
#產生輸入檔:
$ for i in $(seq 1 600000);執行echo server$((random�0 100)),$random,$random,$random;完成>sample.csv
運行 perl 程式碼:
$ time { perl -ne 'chomp; print "$_";' <sample.csv >out1.txt; } real 0m0.226s user 0m0.102s sys 0m0.048s
再次運行它以確保它已從檔案系統快取中讀取輸入檔案:
$ time { perl -ne 'chomp; print "$_";' <sample.csv >out1.txt; } real 0m0.123s user 0m0.090s sys 0m0.033s
注意執行時間是如何減少的。
在快取的輸入上執行 go 程式碼:
$ time { ./chomp <sample.csv >out2.txt; } real 0m0.063s user 0m0.032s sys 0m0.032s
確保結果相同:
$ cmp out1.txt out2.txt
#如您所見,在我的帶有 ssd 的 linux/amd64
系統上,結果大致相同。
嗯,我還應該指出,為了獲得合理的結果,您需要運行每個命令,例如1000 次,並對每個批次中的結果進行平均,然後比較這些數字,但我認為這足以證明什麼您的方法存在的問題是。
還有一件事需要考慮:這兩個程式的運行時間絕大多數由檔案系統i/o 主導,因此,如果您認為go 會更快,那麼您的期望是沒有根據的:這兩個程式大部分時間sleep 在核心的系統呼叫read(2)
和write(2)
。在某些涉及 cpu 運算的情況下,go 程式可能比 perl 程式更快(特別是如果它是為利用多核心系統而編寫的),但您的範例根本不是這種情況。
哦,只是為了明確未說明的事實:雖然go 語言規範沒有說明aot,而go run
是一種針對一次性一次性演出的hack,不嚴肅的工作,也不執行任何嚴重複雜程度的程式碼。簡而言之,go-that-you-are-using 並不是一種解釋性語言,儘管 go run
的可用性可能使它看起來如此。事實上,它執行正常 go build
會執行的操作,然後運行生成的可執行文件,然後將其丟棄。
您可能會想說perl 也處理“源代碼”,但perl 解釋器針對處理腳本和go 的構建工具鏈進行了高度優化——同時與大多數其他編譯語言相比速度快得驚人——未針對此進行最佳化。
可能更明顯的區別是,perl 解釋器實際上解釋您的(非常簡單的)腳本,而chomp
和print
是所謂的「內建函數”,很容易提供給由解釋器執行腳本。與構建go 程式相比,編譯器解析原始程式碼檔案並將其轉換為機器碼,連結器實際上讀取go 標準庫的編譯包的檔案- 所有這些都是import
ed, -從它們,組合所有這些機器碼並寫出一個可執行圖像檔案(這很像perl
二進位檔案本身!);當然,這是一個非常消耗資源的過程,與實際的程式執行無關。
以上是為什麼 Go 中讀寫檔案比 Perl 慢很多?的詳細內容。更多資訊請關注PHP中文網其他相關文章!