首頁 > 後端開發 > Golang > 主體

為什麼 Go 中讀寫檔案比 Perl 慢很多?

王林
發布: 2024-02-09 21:30:24
轉載
865 人瀏覽過

为什么 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 倍?

解決方法

您正在將蘋果與橘子進行比較。

至少有兩個方法錯誤:

  1. 您的perl 咒語測量cat 如何讀取檔案並透過pipe(2) 發送其內容,而perl 從那裡讀取數據,對其進行處理並將結果寫入其標準輸出。

  2. 你的圍棋咒語

    • 測量 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 並進行測量:

  1. 建構程式碼:

    $ go build chomp.go

  2. #產生輸入檔:

    $ for i in $(seq 1 600000);執行echo server$((random�0 100)),$random,$random,$random;完成>sample.csv

  3. 運行 perl 程式碼:

    $ time { perl -ne 'chomp; print "$_";' <sample.csv >out1.txt; }
    
    real    0m0.226s
    user    0m0.102s
    sys 0m0.048s
    登入後複製
  4. 再次運行它以確保它已從檔案系統快取中讀取輸入檔案:

    $ time { perl -ne 'chomp; print "$_";' <sample.csv >out1.txt; }
    
    real   0m0.123s
    user   0m0.090s
    sys    0m0.033s
    登入後複製

    注意執行時間是如何減少的。

  5. 在快取的輸入上執行 go 程式碼:

    $ time { ./chomp <sample.csv >out2.txt; }
    
    real   0m0.063s
    user   0m0.032s
    sys    0m0.032s
    登入後複製
  6. 確保結果相同:

    $ cmp out1.txt out2.txt

  7. #如您所見,在我的帶有 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 解釋器實際上解釋您的(非常簡單的)腳本,而chompprint 是所謂的「內建函數”,很容易提供給由解釋器執行腳本。與構建go 程式相比,編譯器解析原始程式碼檔案並將其轉換為機器碼,連結器實際上讀取go 標準庫的編譯包的檔案- 所有這些都是imported, -從它們,組合所有這些機器碼並寫出一個可執行圖像檔案(這很像perl 二進位檔案本身!);當然,這是一個非常消耗資源的過程,與實際的程式執行無關。

    以上是為什麼 Go 中讀寫檔案比 Perl 慢很多?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:stackoverflow.com
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
最新問題
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!