golang的GOMAXPROCS

  • 介绍

    GOMAXPROCS是golang运行时环境的一个参数,控制着同时执行golang代码的操作系统线程的最大数量(M),即影响调度器分配Goroutine到多少个操作系统线程。这些线程由操作系统分配到机器的逻辑核心(P)上执行。

    当GOMAXPROCS=1时,所有Goroutine在单线程上并发运行(通过时间片切换,非真正并行)。

    当GOMAXPROCS>1时,Goroutine可以被分配到多个线程,这些线程又可以被分配到不同的逻辑核心上,从而并行执行在多核cpu上。

  • 默认行为

    Go 1.4 及之前版本,默认 GOMAXPROCS=1。 Go 1.5 及之后版本,GOMAXPROCS = 当前机器的逻辑 CPU 核心数(通过 runtime.NumCPU() 获取)。

  • 设置GOMAXPROCS

    // 环境变量方式
    在go程序运行前,添加/修改 GOMAXPROCS 环境变量
    export GOMAXPROCS=4   # Linux/Mac
    set GOMAXPROCS=4      # Windows

    // 代码方式
    在程序开头,使用runtime包的GOMAXPROCS方法设置
    runtime.GOMAXPROCS(4)
    // 其中,runtime.GOMAXPROCS接收的值如果小于等于0,会返回当前的GOMAXPROCS值,而不修改。

    // 两种方式同时设置的情况下,环境变量方式优先级会更高
  • 小坑:docker内运行golang程序

    // 在docker内,golang程序感知cpu核心数的功能可能不准确。比如本人遇到的情况,容器cpu设置250m(即0.25核)的情况下,golang程序却感知到了4个核心,而机器实际是8个核心。
    // 这种情况下,golang默认情况下会设置GOMAXPROCS=4,会将协程分配给4个操作线程,而实际能用上的逻辑核心是1,这就导致4个线程争抢一个逻辑核心的资源,那么就会带来不必要的线程上下文切换消耗。
    // 如果面对cpu核心更多的机器,比如32核心,那么这个问题就会更加严重。
    // 所以在docker中运行golang程序,最好自己设置一下GOMAXPROCS。golang官方已经出了相关的提案,希望golang能正确感知容器可利用的核心数,也许未来的版本中,就不需要自己设置了。
posted @ 2025-04-12 16:16  CJTARRR  阅读(195)  评论(0)    收藏  举报