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

當 goroutine 數量增加時,Go 程式會變慢

WBOY
發布: 2024-02-09 22:10:10
轉載
1294 人瀏覽過

当 goroutine 数量增加时,Go 程序会变慢

當 goroutine 數量增加時,Go 程式會變慢。這是因為 goroutine 的調度和切換會引入額外的開銷,從而導致程式效能下降。雖然 goroutine 在提供並發效能方面表現出色,但是過多的 goroutine 會導致執行緒競爭和資源爭用,進而影響程式的執行效率。為了避免這種情況發生,我們需要合理管理和控制 goroutine 的數量,確保程式能夠有效率地運作。在本文中,php小編柚子將為您介紹一些優化 goroutine 效能的方法和技巧,幫助您提升 Go 程式的執行效率。

問題內容

我正在為我的平行課程做一個小項目,我已經嘗試使用緩衝通道、無緩衝通道、不使用指向切片的指標的通道等。此外,盡可能嘗試優化它(不是當前狀態)但我仍然得到相同的結果:增加 goroutine 數量(甚至增加 1)會減慢整個程式的速度。有人可以告訴我我做錯了什麼嗎?在這種情況下甚至可以增強並行性嗎?

這是部分程式碼:

func main() {

    rand.seed(time.now().unixmicro())

    numagents := 2

    fmt.println("please pick a number of goroutines: ")
    fmt.scanf("%d", &numagents)

    numfiles := 4
    fmt.println("how many files do you want?")
    fmt.scanf("%d", &numfiles)
    start := time.now()

    numassist := numfiles
    channel := make(chan []file, numagents)
    files := make([]file, 0)

    for i := 0; i < numagents; i++ {
        if i == numagents-1 {
            go generatefiles(numassist, channel)
        } else {
            go generatefiles(numfiles/numagents, channel)
            numassist -= numfiles / numagents
        }
    }

    for i := 0; i < numagents; i++ {
        files = append(files, <-channel...)
    }

    elapsed := time.since(start)
    fmt.printf("function took %s\n", elapsed)
}
登入後複製
func generatefiles(numfiles int, channel chan []file) {
    magicnumbersmap := getmap()
    files := make([]file, 0)

    for i := 0; i < numfiles; i++ {
        content := randelementfrommap(&magicnumbersmap)

        length := rand.intn(400) + 100
        hexslice := gethex()

        for j := 0; j < length; j++ {
            content = content + hexslice[rand.intn(len(hexslice))]
        }

        hash := getsha1hash([]byte(content))

        file := file{
            content: content,
            hash:    hash,
        }

        files = append(files, file)
    }

    channel <- files

}
登入後複製

預期透過增加 goroutines,程式會運行得更快,但達到一定數量的 goroutines,此時透過增加 goroutines,我將獲得相同的執行時間或稍慢一些。

編輯:使用的所有功能:

import (
    "crypto/sha1"
    "encoding/base64"
    "fmt"
    "math/rand"
    "time"
)

type File struct {
    content string
    hash    string
}

func getMap() map[string]string {
    return map[string]string{
        "D4C3B2A1": "Libcap file format",
        "EDABEEDB": "RedHat Package Manager (RPM) package",
        "4C5A4950": "lzip compressed file",
    }
}

func getHex() []string {
    return []string{
        "0", "1", "2", "3", "4", "5",
        "6", "7", "8", "9", "A", "B",
        "C", "D", "E", "F",
    }
}

func randElementFromMap(m *map[string]string) string {
    x := rand.Intn(len(*m))
    for k := range *m {
        if x == 0 {
            return k
        }
        x--
    }
    return "Error"
}

func getSHA1Hash(content []byte) string {
    h := sha1.New()
    h.Write(content)
    return base64.URLEncoding.EncodeToString(h.Sum(nil))
}
登入後複製

解決方法

簡單來說 - 檔案產生程式碼不夠複雜,不足以證明並行執行的合理性。所有上下文切換和透過通道移動資料都會消耗並行處理的所有好處。

如果你在generatefiles 函數的循環中加入類似time.sleep(time.millisecond * 10) 的內容,就好像它在做更複雜的事情一樣,你會看到你期望看到的東西- 更多的goroutine 工作得更快。但同樣,只有到一定程度,並行處理的額外工作才會帶來好處。

另請注意,程式最後一位的執行時間:

for i := 0; i < numAgents; i++ {
    files = append(files, <-channel...)
}
登入後複製

直接取決於 goroutine 的數量。由於所有 goroutine 大約同時完成,因此該循環幾乎不會與您的工作線程並行執行,並且運行所需的時間只是添加到總時間中。

接下來,當您多次追加到 files 切片時,它必須成長幾次並將資料複製到新位置。您可以透過最初建立一個切片來填充所有結果元素(幸運的是,您確切知道需要多少元素)來避免這種情況。

以上是當 goroutine 數量增加時,Go 程式會變慢的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:stackoverflow.com
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板