为什么这个程序在使用goroutines时表现不佳?

时间:2013-06-27 13:05:49

标签: performance concurrency grep go

我正在学习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目录中存在的文件数。主要等到所有goroutines完成工作。

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

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

2 个答案:

答案 0 :(得分:6)

尝试使用更多内核。此外,使用更好的根目录进行比较,例如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

答案 1 :(得分:4)

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