2013-04-17 34 views
1

我有一些问题与goroutines。为什么这段代码执行〜125ms的(注意顺序执行):goroutines导致重大减速和头痛

package main 

import (
    "os/exec" 
    "time" 
    "fmt" 
) 

func main() { 
    cmd := exec.Command("lessc", "--yui-compress", "test.less") 
    n := 2000 
    start := time.Now() 
    for i := 0; i < n; i++ { 
    cmd.Run() 
    } 
    finish := time.Now() 

    fmt.Printf("Program took %v to run\n", finish.Sub(start)) 
} 

此代码时需要约20秒(并发执行使用够程):

package main 

import (
    "os/exec" 
    "time" 
    "fmt" 
) 

func main() { 
    cmd := exec.Command("lessc", "--yui-compress", "test.less") 
    ch := make(chan bool) 
    n := 2000 
    start := time.Now() 
    for i := 0; i < n; i++ { 
    go lessc(ch, cmd) 
    } 
    fmt.Println(n, " goroutines started.") 
    for i := 0; i < n; i++ { 
    _ = <-ch 
    } 
    finish := time.Now() 

    fmt.Printf("Program took %v to run\n", finish.Sub(start)) 
} 

func lessc(ch chan bool, c *exec.Cmd) { 

    c.Run() 
    ch <- true 
} 

使用去1.0.3上i7 720QM(4C/8T)8GB RAM linux/x86-64 也使用1.0.2构建和测试,并在同一台机器上得到同样的问题。

编辑:由@jnml解决下面。如果有人关心这里的新的固定并发代码,它是:

package main 

import (
    "os/exec" 
    "time" 
    "fmt" 
) 

func main() { 
    ch := make(chan bool) 
    n := 2000 
    start := time.Now() 
    for i := 0; i < n; i++ { 
    go lessc(ch) 
    } 
    fmt.Println(n, " goroutines started.") 
    for i := 0; i < n; i++ { 
    _ = <-ch 
    } 
    finish := time.Now() 

    fmt.Printf("Program took %v to run\n", finish.Sub(start)) 
} 

func lessc(ch chan bool) { 

    cmd := exec.Command("lessc", "--yui-compress", "test.less") 
    cmd.Run() 
    ch <- true 
} 
+0

我正在使用Go 1.0.3。我将恢复到1.0.2并重建它们以查看它是否对我有所帮助。 –

+0

我使用go 1.0.2构建它之后,我仍然遇到同样的问题。 –

+0

目前还不清楚你的测试应该做什么,但'testing.B'将会更好地测试两段代码之间的性能差异。 – Dustin

回答

11

IMO你的程序是不正确的。它包含一个竞争条件,因此可以从字面上做任何事情。任何时机都没有意义。

你正在创建一个exec.Cmd,然后同时(==数据种族)从几个够程履行Run方法。 exec.Cmd从来没有提到它可以重复使用多次Run - 即使是连续的。

exec.Cmd有一些状态被exec.Command初始化,并且在执行Run后有一个不同的状态。 IOW,执行Run方法后,状态不再被初始化,可能不适合另一个Run

+3

为了测试这个,我把'cmd:= exec.Command(“lessc”,“--ui-compress”,“test.less”)'移到了func lessc中,并将声明改为不需要指向cmd的指针。现在该程序的执行时间与顺序程序相似。感谢您向我解释这一点。 –