Google Go的goroutine中断模式(速度问题)

huangapple go评论118阅读模式
英文:

interrupt pattern for google go goroutine (speed issue)

问题

我运行了一个goroutine来递增一个计数器,可以通过命令行输入"t"来中断。

select语句中,如果我选择使用default:,计数器变量j会不断增加。这对我来说看起来很正常。

然而,如果我选择使用case <-time.After(100*time.Microsecond):,计数器j在一秒钟内只增加到大约60左右,而不是10,000。

实际上,无论我在time.After()中放入什么值,我只能得到大约60Hz的速率通过select语句运行。

为什么会这样?

  1. package main
  2. import (
  3. "bufio"
  4. "fmt"
  5. "os"
  6. "strings"
  7. "time"
  8. )
  9. func main() {
  10. message := make(chan string)
  11. go check_input(message)
  12. work_loop(message)
  13. }
  14. func work_loop(message chan string) {
  15. //var j [][]int
  16. var j int
  17. t0:=time.Now()
  18. Loop:
  19. for {
  20. select {
  21. case msg := <-message:
  22. if msg == "terminate" {
  23. //fmt.Println("end task")
  24. t1:=time.Now()
  25. fmt.Println(j)
  26. fmt.Println("total duration:", t1.Sub(t0))
  27. break Loop
  28. }
  29. case <-time.After(100 * time.Microsecond):
  30. //default:
  31. //do work here
  32. j += 1
  33. fmt.Println(j)
  34. break
  35. }
  36. }
  37. //fmt.Println("exit work loop")
  38. }
  39. func check_input(msg chan string) {
  40. reader := bufio.NewReader(os.Stdin)
  41. for {
  42. line, err := reader.ReadString('\n')
  43. if err != nil {
  44. // You may check here if err == io.EOF
  45. break
  46. }
  47. if strings.TrimSpace(line) == "t" {
  48. msg <- "terminate"
  49. }
  50. }
  51. }
英文:

I run a goroutine to increment a counter, which can be interrupted by command line input "t\n"

In the select statement, if I choose to use default:, the counter variable j flies forword. That seems normal to me.

However, if I choose to use case &lt;-time.After(100*time.Microsecond):, the counter j only adds up to 60 or so in one second, instead of 10,000.

In fact no matter what value I put in time.After(), I only get about 60Hz rate running through the select statement.

Why?

  1. package main
  2. import (
  3. &quot;bufio&quot;
  4. &quot;fmt&quot;
  5. &quot;os&quot;
  6. &quot;strings&quot;
  7. &quot;time&quot;
  8. )
  9. func main() {
  10. message := make(chan string)
  11. go check_input(message)
  12. work_loop(message)
  13. }
  14. func work_loop(message chan string) {
  15. //var j [][]int
  16. var j int
  17. t0:=time.Now()
  18. Loop:
  19. for {
  20. select {
  21. case msg := &lt;-message:
  22. if msg == &quot;terminate&quot; {
  23. //fmt.Println(&quot;end task&quot;)
  24. t1:=time.Now()
  25. fmt.Println(j)
  26. fmt.Println(&quot;total duration:&quot;, t1.Sub(t0))
  27. break Loop
  28. }
  29. case &lt;-time.After(100 * time.Microsecond):
  30. //default:
  31. //do work here
  32. j += 1
  33. fmt.Println(j)
  34. break
  35. }
  36. }
  37. //fmt.Println(&quot;exit work loop&quot;)
  38. }
  39. func check_input(msg chan string) {
  40. reader := bufio.NewReader(os.Stdin)
  41. for {
  42. line, err := reader.ReadString(&#39;\n&#39;)
  43. if err != nil {
  44. // You may check here if err == io.EOF
  45. break
  46. }
  47. if strings.TrimSpace(line) == &quot;t&quot; {
  48. msg &lt;- &quot;terminate&quot;
  49. }
  50. }
  51. }

答案1

得分: 1

这与time.Timer的精度有关。查看time.After的文档:

> [...] 它等价于NewTimer(d).C。

以及time.NewTimer的文档:

> NewTimer创建一个新的计时器,在至少持续时间d之后,将在其通道上发送当前时间。

(重点在于“至少”)

这是因为NewTimer委托给一个运行时(依赖于操作系统)计时器,使得该计时器的行为取决于底层操作系统(以及Go集成的实现)。

总的来说,根据我的经验,在任何语言中,特别是在Windows XP上,亚毫秒级的精度在跨平台支持方面并不好。

英文:

It has to do with the precision of time.Timer. Looking at the documentation of time.After:

> [...] It is equivalent to NewTimer(d).C.

and the documentation of time.NewTimer:

> NewTimer creates a new Timer that will send the current time on its channel after at least duration d.

(emphasis mine)

The reason for this is that NewTimer delegates to a runtime (OS-dependent) timer,making the behavior of this timer dependent on the underlying OS (and the implementation of the Go integration).

In general, it is my experience that sub-millisecond granularity does not have good cross-platform support in any language, especially on Windows XP.

huangapple
  • 本文由 发表于 2013年11月8日 05:59:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/19847533.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定