為什麼 Go 中讀寫檔案比 Perl 慢很多?
為什麼 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
從那裡讀取數據,對其進行處理並將結果寫入其標準輸出。你的圍棋咒語
- 測量 go 工具鏈的完整建置過程(包括編譯、連結和寫出可執行映像檔)然後執行 已編譯程式的組成部分,以及
- 測量對標準輸出的無緩衝寫入(
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中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

complex 類型用於表示 C 語言中的複數,包含實部和虛部。其初始化形式為 complex_number = 3.14 + 2.71i,實部可透過 creal(complex_number) 訪問,虛部可透過 cimag(complex_number) 存取。此類型支援常用的數學運算,如加、減、乘、除和取模。此外,還提供了一組用於處理複數的函數,如 cpow、csqrt、cexp 和 csin。

fabs() 函數是 C++ 中的一個數學函數,用於計算浮點數的絕對值,去除負號並傳回正值。它接受一個浮點參數,並傳回一個 double 類型的絕對值。例如,fabs(-5.5) 將傳回 5.5。此函數適用於浮點數,其精確度受底層硬體影響。

prime 是 C++ 中的關鍵字,表示質數類型,只能被 1 和本身整除,用作布林類型指示給定值是否為質數,為質數則為 true,否則為 false。

std 是 C++ 中包含標準函式庫元件的命名空間。為了使用 std,需要使用 "using namespace std;" 語句。直接使用 std 命名空間中的符號可以簡化程式碼,但建議僅在需要時使用,以避免命名空間污染。

C++智慧指標的生命週期:建立:分配記憶體時建立智慧指標。所有權轉移:透過移動操作轉移所有權。釋放:智慧指標離開作用域或被明確釋放時釋放記憶體。物件銷毀:所指向物件被銷毀時,智慧型指標成為無效指標。

C++ 中的 min 函數可傳回多個值中的最小值。其語法為:min(a, b),其中 a 和 b 為要比較的值。也可以指定一個比較函數,以支援不支援 < 運算子的類型。 C++20 引入了 std::clamp 函數,可處理三個或更多值的最小值。

在 C++ 中,prime 指質數,即大於 1 且只能被 1 和它本身整除的自然數。質數在密碼學、數學問題和演算法中應用廣泛。產生質數的方法包括厄拉多塞篩法、費馬小定理和米勒-拉賓檢定。 C++ 標準函式庫中提供 isPrime 函數判斷是否為質數,nextPrime 函數傳回大於給定值的最小質數,prevPrime 函數傳回小於給定值的最小質數。

C++並發程式框架具有以下選項:輕量級執行緒(std::thread);執行緒安全的Boost並發容器和演算法;用於共享記憶體多處理器的OpenMP;高效能ThreadBuildingBlocks(TBB);跨平台C++並發互操作庫(cpp-Concur)。
