golang其实也可以优先调度

dearplain · · 992 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

 

线上一个服务有个严重问题,处理消息数1k/s提升不上去,经过查看是阻塞在了一个新加的函数上,这个函数负责收集信息,送到一个channel上,再由某个函数处理,这个处理函数很简单,看不出任何问题,最大的特点是为了不加锁,只起一个goroutine。

问题很明显了,只起一个goroutine,当系统繁忙和存在大量goroutine的时候,会得不到调度,导致收集函数阻塞,进而导致消息处理数上不去。

该获得调度的没有被调度,不该获得调度的却获得调度了,而go runtime不可能知道那个goroutine应该被调度,只能是公平调度,但是公平调度却造成了堵塞!

这种问题其实很普遍,不是一个goroutine的问题!就算你开了多个goroutine,仍然可能得不到调度!(当然,是在繁忙的时候,大部分时候不存在这种问题)

这篇文章《记一次latency问题排查:谈Go的公平调度的缺陷》也谈到go这个问题,作者认为问题无解。

其实我们可以试试,golang提供的一个更简单的方法,runtime.LockOSThread()。

官方介绍:

LockOSThread wires the calling goroutine to its current operating system thread. Until the calling goroutine exits or calls UnlockOSThread, it will always execute in that thread, and no other goroutine can.

重点在于no other goroutine can,LockOSThread本来是设计给opengl等东西用的,但是从官方这个说明来看,我们可以利用它做优先调度,将某个goroutine锁定到某个系统线程,这个线程只调度这个goroutine,进而可以被优先调度(相对其他goroutine)。因为系统线程是根据时间片调度的,因此能让这个goroutine得到获得更多时间。

下面的test,显示了runtime.LockOSThread()的确能影响调度,注释掉runtime.LockOSThread(),有2-60倍的时间差。

package main

import (
    "fmt"
    "os"
    "runtime"
    "time"
)

func main() {

    var ch = make(chan bool, 20000)
    var begin = make(chan bool)

    go func() {
        runtime.LockOSThread()
        <-begin
        fmt.Println("begin")
        tm := time.Now()
        for i := 0; i < 10000000; i++ {
            <-ch
        }
        fmt.Println(time.Now().Sub(tm))
        os.Exit(0)
    }()

    for i := 0; i < 50000; i++ {
        // 负载
        go func() {
            var count int
            load := 100000
            for {
                count++
                if count >= load {
                    count = 0
                    runtime.Gosched()
                }
            }
        }()
    }

    for i := 0; i < 20; i++ {
        go func() {
            for {
                ch <- true
            }
        }()
    }

    fmt.Println("all start")
    begin <- true

    select {}
}

 


有疑问加站长微信联系(非本文作者)

本文来自:博客园

感谢作者:dearplain

查看原文:golang其实也可以优先调度

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

992 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传