【问题标题】:goroutines causing major slowdowns and headaches导致严重减速和头痛的 goroutines
【发布时间】:2013-04-17 10:20:39
【问题描述】:

我在使用 goroutines 时遇到了一些问题。为什么这段代码在 ~125ms 内执行(注意顺序执行):

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 秒时(使用 goroutine 并发执行):

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
}

在 i7 720QM (4C/8T) 8GB RAM linux/x86-64 上使用 go 1.0.3 还使用 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
}

【问题讨论】:

  • 我使用的是 Go 1.0.3。我将恢复到 1.0.2 并重建它们,看看它是否对我有影响。
  • 使用 go 1.0.2 构建后,我仍然遇到同样的问题。
  • 不清楚您的测试应该做什么,但testing.B 会更好地测试两段代码之间的性能差异。

标签: concurrency go goroutine


【解决方案1】:

IMO 您的程序不正确。它包含一个竞争条件,因此可以做任何事情。任何时间都没有意义。

您正在创建 一个 exec.Cmd,然后同时(== 数据竞争)从多个 goroutine 执行其 Run 方法。 exec.Cmd 从未提及它可以重复使用一次以上Run - 即使是连续使用。

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

【讨论】:

  • 为了测试这一点,我将 cmd := exec.Command("lessc", "--yui-compress", "test.less") 移动到 func lessc 并将声明更改为不需要指向 cmd 的指针。该程序现在的执行时间与顺序程序相似。感谢您向我解释这一点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-13
  • 2018-09-23
  • 2018-04-05
  • 1970-01-01
  • 2013-11-29
相关资源
最近更新 更多