【问题标题】:Why is this program not performing better with goroutines?为什么这个程序在使用 goroutine 时表现不佳?
【发布时间】:2013-06-25 00:05:26
【问题描述】:

我正在学习 Go 编程语言。请考虑以下程序,

package main

import (
    "fmt"
    "bytes"
    "os"
    "os/exec"
    "path/filepath"
    "sync"
)

func grep(file string) {
    defer wg.Done()

    cmd := exec.Command("grep", "-H", "--color=always", "add", file)
    var out bytes.Buffer
    cmd.Stdout = &out
    cmd.Run()
    fmt.Printf("%s\n", out.String())
}

func walkFn(path string, info os.FileInfo, err error) error {
    if !info.IsDir() {
        wg.Add(1)
        go grep (path)
    }
    return nil
}

var wg sync.WaitGroup

func main() {
    filepath.Walk("/tmp/", walkFn)
    wg.Wait()
}

这个程序遍历/tmp 目录中的所有文件,并在goroutine 中对每个文件执行grep。所以这将产生n goroutines,其中n/tmp 目录中存在的文件数。 Main 等待所有 goroutine 完成工作。

有趣的是,这个程序在使用和不使用 goroutine 的情况下执行的时间是相同的。尝试运行go grep (path, c)grep (path, c)(执行此操作时需要评论频道内容)。

我期待 goroutine 版本运行得更快,因为多个 grep 同时运行。但它几乎在相同的时间内执行。我想知道为什么会这样?

【问题讨论】:

    标签: performance concurrency grep go


    【解决方案1】:

    尝试使用更多内核。此外,出于比较目的,请使用更好的根目录,例如 Go 目录。 SSD 也有很大的不同。例如,

    func main() {
        runtime.GOMAXPROCS(runtime.NumCPU())
        goroot := "/home/peter/go/"
        filepath.Walk(goroot, walkFn)
        wg.Wait()
        fmt.Println("GOMAXPROCS:", runtime.GOMAXPROCS(0))
    }
    
    GOMAXPROCS: 1
    real    0m10.137s
    user    0m2.628s
    sys     0m6.472s
    
    GOMAXPROCS: 4
    real    0m3.284s
    user    0m2.492s
    sys     0m5.116s
    

    【讨论】:

    • 这就不同了。为什么需要显式设置GOMAXPROCS?它不会默认为NumCPU() 吗?
    • 推荐的方法是在启动程序之前设置环境变量 GOMAXPROCs,而不是通过运行时。像这样,您可以轻松控制程序的这个特定实例将在内核上消耗多少。
    【解决方案2】:

    您的程序的性能与磁盘的速度有关(或 ram,如果 /tmp 是 ram 磁盘):计算为 I/O bound。无论有多少个 goroutine 并行运行,它的读取速度都不会比这更快。

    【讨论】:

      猜你喜欢
      • 2020-03-03
      • 2014-03-12
      • 2017-07-14
      • 2021-06-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多