【问题标题】:Gogoutine schedule algorithmGogoutine 调度算法
【发布时间】:2014-11-09 11:35:53
【问题描述】:
package main

import ()

func main() {
    msgQueue := make(chan int, 1000000)
    netAddr := "127.0.0.1"
    token := make(chan int, 10)
    for i := 0; i < 10; i++ {
        token <- i
    }
    go RecvReq(netAddr, msgQueue)
    for {
        select {
         case req := <-msgQueue:
            go HandleReq(req, token)
        }
    }
}

func RecvReq(addr string,msgQueue chan int){
     msgQueue<-//get from network
}

func HandleReq(msg int, token chan int) {
//step 1
t := <-token
//step 2
//codo here...(don't call runtime.park)
//step 3
//code here...(may call runtime.park)
//step 4
token <- t
}

系统:1cpu 2core

Go 版本:go1.3 linux/amd64

问题描述:

msgQueue revc 一直由 RecvReq 请求,然后主 goroutine 一直创建新的 goroutine,但是等待的 goroutine 一直等待。前 10 个 goroutine 在第 3 步停止,新的 goroutine 在第 1 步停止。

Q1:如何让等待的goroutine在新的goroutine一直被创建的时候运行。

Q2:如何平衡RevcReq和HandleReq? Revc msg 速率比 Handle msg 快 10 倍。

【问题讨论】:

  • 您似乎在使用 token 通道缓冲区之前对其进行了填充。然后您将其弹出 (10-1=9) .. 然后将值直接放回 (9+1=10)。因此,您的 token 频道基本上是无缓冲的。因此,算法两侧的处理速度大相径庭。我建议停止 token 预填充和缓冲区对齐。
  • 你可以让十个 goroutine 一直在运行,每个 goroutine 都有一个令牌作为局部变量,也许。我不确定这些观察是否有帮助,但是 1) 调度程序不能保证给定的 goroutine 将运行,直到几乎没有其他东西可以运行,2) 巨大的缓冲通道可能导致奇怪的行为,3) 没有完整的很难调试有问题的可运行代码示例。
  • Heh 和 4) 确保您设置了 GOMAXPROCS。 :)
  • 为什么不使用真正的消息队列,比如 nsq 或 rabbit?

标签: go goroutine


【解决方案1】:

唉,从你的问题来看,这不是很清楚。但是这里有几个问题。

  1. 您创建一个大小为 n 的缓冲通道,然后将 n 个项目插入其中。不要这样做 - 或者更清楚地说,在你知道需要它之前不要这样做。缓冲通道通常属于“过早优化”类别。从无缓冲通道开始,这样你就可以弄清楚 goroutines 是如何协作的。当它工作时(没有死锁),测量性能,添加缓冲,再试一次。

  2. 您的select 只有一名守卫。所以它的行为就像select 不存在,而案例主体是那里唯一的代码。

  3. 您正在尝试为每条消息生成新的 goroutine。这真的是你想要的吗?您可能会发现可以使用 goroutines 的静态网格,在您的情况下可能是 10 个,结果可能是一个意图更清晰的程序。它还可以节省一点点,因为运行时不必动态生成和清理 goroutine(但是,在担心效率低下之前,您应该首先关注正确的行为)。

  4. 操场示例中缺少您的 RecvReq,无法执行。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-05-14
    • 2015-06-03
    • 2011-04-16
    • 2011-03-15
    • 2012-07-11
    • 2012-11-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多