目錄
問題內容
解決方法
首頁 後端開發 Golang 為什麼 Go 中讀寫檔案比 Perl 慢很多?

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

Feb 09, 2024 pm 09:30 PM
標準函式庫

为什么 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中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

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

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

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

熱門話題

Java教學
1658
14
CakePHP 教程
1415
52
Laravel 教程
1309
25
PHP教程
1257
29
C# 教程
1231
24
_complex在c語言中的用法 _complex在c語言中的用法 May 08, 2024 pm 01:27 PM

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

c++中fabs是什麼意思 c++中fabs是什麼意思 May 08, 2024 am 01:15 AM

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

c++中prime什麼意思 c++中prime什麼意思 May 07, 2024 pm 11:33 PM

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

c++中std::怎麼用 c++中std::怎麼用 May 09, 2024 am 03:45 AM

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

C++ 智慧指標:全面剖析其生命週期 C++ 智慧指標:全面剖析其生命週期 May 09, 2024 am 11:06 AM

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

c++中min是什麼意思 c++中min是什麼意思 May 08, 2024 am 12:51 AM

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

prime在c++中是什麼意思 prime在c++中是什麼意思 May 07, 2024 pm 11:24 PM

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

C++ 中有哪些並發程式框架和函式庫?它們各自的優點和限制是什麼? C++ 中有哪些並發程式框架和函式庫?它們各自的優點和限制是什麼? May 07, 2024 pm 02:06 PM

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

See all articles