• GOMAXPROCS你设置对了吗?


    1. 前言

    有圈子的朋友介绍 uber-go/automaxprocs, 我才发现之前在docker中, Golang程序设置的GOMAXPROCS不正确,有必要在重新回顾一下了。

    2. Go 调度器: M, P 和 G

    我们知道在Go scheduler中,G代表goroutineP代表Logical ProcessorM是操作系统线程。在绝大多数时候,其实P的数量和M的数量是相等。 每创建一个p, 就会创建一个对应的M
    只有少数情况下,M的数量会大于P

    golang runtime是有个sysmon的协程,他会轮询的检测所有的P上下文队列,只要 G-M 的线程长时间在阻塞状态,那么就重新创建一个线程去从runtime P队列里获取任务。先前的阻塞的线程会被游离出去了,当他完成阻塞操作后会触发相关的callback回调,并加入回线程组里。简单说,如果你没有特意配置runtime.SetMaxThreads,那么在没有可复用的线程的情况下,会一直创建新线程。

    3. GOMAXPROCS的取值

    3.1 虚拟机和物理机

    我们知道可以通过

    runtime.GOMAXPROCS()
    

    来了设定P的值

    Go 1.5开始, Go的GOMAXPROCS默认值已经设置为 CPU的核数, 这允许我们的Go程序充分使用机器的每一个CPU,最大程度的提高我们程序的并发性能。

    但其实对于IO密集型的场景,我们可以把GOMAXPROCS的值超过CPU核数,在笔者维护的某个服务中,将GOMAXPROCS设为CPU核数的2倍,压测结果表明,吞吐能力大概能提升10%

    3.2 容器中

    在容器中,Golang程序获取的是宿主机的CPU核数导致GOMAXPROCS设置的过大。比如在笔者的服务中,宿主机是48cores,而实际container只有4cores。
    线程过多,会增加上线文切换的负担,白白浪费CPU。
    uber-go/automaxprocs 可以解决这个问题

    package main
    
    import (
        "fmt"
        _ "go.uber.org/automaxprocs"
        "runtime"
    )
    
    func main() {
        // Your application logic here.
        fmt.Println("real GOMAXPROCS", runtime.GOMAXPROCS(-1))
    }
    

    另外也可以通过设置环境变量GOMAXPROCS来改变Golang程序的GOMAXPROCS默认值

  • 相关阅读:
    0513装饰器
    python05-09
    python第四讲
    第四讲作业
    Python第二天
    课后实践之嵌入式基础20155314
    20155314 《信息安全系统设计基础》课程总结
    2017-2018-1 20155314 《信息安全系统设计基础》第14周学习总结
    2017-2018-1 20155314《信息安全系统设计基础》实验五 通讯协议设计
    2017-2018-1 20155314 《信息安全系统设计基础》第13周学习总结
  • 原文地址:https://www.cnblogs.com/ExMan/p/15240251.html
Copyright © 2020-2023  润新知