约束 GOMAXPROCS 带来的收益 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
GopherDaily
V2EX    Go 编程语言

约束 GOMAXPROCS 带来的收益

  •  
  •   GopherDaily 2023-01-18 16:29:39 +08:00 2634 次点击
    这是一个创建于 999 天前的主题,其中的信息可能已经有所发展或是发生改变。

    最近看了一遍 runtime ,去尝试了之前遗留的一个工作:调整 k8s 中容器的 GOMAXPROCS ,效果还不错。

    在 11:35 左右, 我们将应用的 GOMAXPROCS 从默认的 32/64 主动设置为 4, 对比 14:30 和 11:30 的数据可以看到:

    • go version: 1.17
    • 线程数量从 49 下降到 13, 符合预期
    • 受业务影响, QPS +13%
    • 接口平均响应时间 -9%, CPU -5%
    • GC 的耗时 -59%, STW(StopTheWorld) 的时间 -12%
    • goroutine 在 Runnable 停留的时间 +50%

    gomaxprocs_heavy_gc.png

    第 1 条附言    2023-01-18 17:12:00 +08:00
    GMP 中的 M 和 P 数量多了之后,主要的成本在于:
    - go scheduler 的调度成本
    - go gc 的成本
    - os thread 切换的成本,默认 GOMAXPROCS 等同于 CPU 就是为了尽量一个 M 一个 C ,避免上下文切换
    第 2 条附言    2023-01-18 17:18:11 +08:00
    https://github.com/j2gg0s/j2gg0s/blob/main/20230118_go_%E7%BA%A6%E6%9D%9FGOMAXPROCS%E5%B8%A6%E6%9D%A5%E7%9A%84%E6%94%B6%E7%9B%8A.md

    GOMAXPROCS 限制了用来并发执行代码的系统线程数量, 默认等于 CPU 的数量. 使用 CPU 做为 GOMAXPROCS 的默认值, 是为了平衡执行效率和调度成本. 我们即希望有尽可能多的线程来提高并行程度, 又不希望系统线程被频繁的切换. 所以在假设基本独占机器资源的前提下, 我们选择 CPU 的数量做为默认的线程数量.

    当我们的代码运行在 k8s 中, 基本面发生了一些改变. 一方面, 几十个应用共享一个宿主机(Node); 另一方面 Go 直接使用宿主机的 CPU 数量做为 GOMAXPROCS 的默认值. 于是出现了一些类似, 应用假设的 CPU 数量是 1, 但是默认创建了 64 个线程的情况.

    这种 k8s 下的默认行为是否合理, 我们很难直接从代码中得出一个结论. 通过控制变量的方式来观察结果似一个不错的选择
    23 条回复    2023-02-09 10:30:38 +08:00
    julyclyde
        1
    julyclyde  
       2023-01-18 16:48:13 +08:00
    那就需要分析一下原因了
    降低并发度之后反而提高了处理能力,说明并发的时候内耗比较大?
    kiwi95
        2
    kiwi95  
       2023-01-18 16:51:41 +08:00 via Android
    说明当前场景下并发调度开销比较大?
    loveuer
        3
    loveuer  
       2023-01-18 16:52:12 +08:00
    可以细说一下主要啥类型的业务么
    chenqh
        4
    chenqh  
       2023-01-18 16:55:33 +08:00
    你这是 k8s 吧,golang 这种不应该是一个进程吃满的吗,又不是 python 那种
    GopherDaily
        5
    GopherDaily  
    OP
       2023-01-18 17:10:25 +08:00
    @julyclyde go scheduler 调度的成本,和 os thread 上下文切换的成本
    julyclyde
        6
    julyclyde  
       2023-01-18 17:13:52 +08:00
    是容器运行吗?
    runtime.NumCPU()和容器的核数是否一致?
    Maboroshii
        7
    Maboroshii  
       2023-01-18 17:15:06 +08:00
    k8s node 上还有其他 pod 吧,都想吃满机器 ,肯定有反效果
    GopherDaily
        8
    GopherDaily  
    OP
       2023-01-18 17:18:26 +08:00
    @loveuer 典型的 web 服务呗
    GopherDaily
        9
    GopherDaily  
    OP
       2023-01-18 17:19:21 +08:00
    @Maboroshii pod 是坑定有的,吃满不至于,我们一般是控制实际使用率在 40%以内,突然的情况下会到 60%
    Aoang
        10
    Aoang  
       2023-01-18 21:24:25 +08:00 via iPhone
    要压榨单机性能最好就别用 k8s (:

    个人实践,丢在 k8s 上的东西都是无状态的应用,开了自动扩缩容其他的就不需要操心了。
    对于有状态或者需要压榨单机性能的,例如数据库都不在 k8s 内。

    另,试着升下版本,GOGC 和 GOMEMLIMIT 还能对程序有进一步的提升。
    Dreamacro
        11
    Dreamacro  
       2023-01-18 22:47:31 +08:00 via iPad
    GopherDaily
        12
    GopherDaily  
    OP
       2023-01-18 23:06:33 +08:00
    @Aoang 自然,但是资源能节约要节约,成本核算都是 OKR
    GopherDaily
        13
    GopherDaily  
    OP
       2023-01-18 23:07:09 +08:00
    @Dreamacro CI/CD 里面直接注入环境变量也行,可控性更高
    hopingtop
        14
    hopingtop  
       2023-01-19 09:39:27 +08:00
    针对 Docker 运行 Go 确实有取宿主机的 CPU 来设置 MAXPROCS.
    当使用 Pod 限制资源的配置时,就不建议手动去调整 MAXPROCS , 这样做不好运维,所以可以选择 Uber 的一个库
    hopingtop
        15
    hopingtop  
       2023-01-19 09:43:21 +08:00
    @hopingtop
    https://github.com/uber-go/automaxprocs

    这库的原理就是取读取 容器里 /sys/fs/cgroup/cpu 里面的值,然后计算出一个合理的 MAXPROCS
    在你 main 函数执行之前通过 import 这个过程去初始化 MAXPROCS
    GopherDaily
        16
    GopherDaily  
    OP
       2023-01-19 10:51:22 +08:00
    @hopingtop 你是站在业务开发的角度来看
    liuxu
        17
    liuxu  
       2023-01-19 12:07:03 +08:00
    嗯,k8s 里面进程数是要手动设置下,除非单 pod ,不然 pod 自动扩展物理机进程数 X^n 上升

    物理机和 k8s 还是有很多细微的差别要处理
    GopherDaily
        18
    GopherDaily  
    OP
       2023-01-19 13:47:43 +08:00
    @liuxu 一直还没去关注,k8s/vm 分配 cpu 时间片的时候会不会主动尽量将单个 pod 聚集到某个 物理 c 上
    liuxu
        19
    liuxu  
       2023-01-19 14:24:47 +08:00
    @GopherDaily 物理 C 是物理 node 还是物理 cpu core ,前者可以用 statefulset 、node selector 和 affility 处理,后者 k8s 没有这个能力也不应该有这个能力
    GopherDaily
        20
    GopherDaily  
    OP
       2023-01-19 14:45:27 +08:00
    @liuxu 真实的、物理的 CPU
    情理上我也觉得 k8s 没有这个能力,但是 resources limit 也在 pod spec 中,所以可能还是可以揣测下
    eudore
        21
    eudore  
       2023-01-22 23:34:39 +08:00
    没配置对,uber 有个库就可以根据 limit 去设置 maxprocs ,jvm 也有相识的内置参数。
    paceewang1
        22
    paceewang1  
       2023-02-09 09:50:35 +08:00
    op 这用的是什么监控呢?
    GopherDaily
        23
    GopherDaily  
    OP
       2023-02-09 10:30:38 +08:00
    @paceewang1 prometheus+grafana
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     6031 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 35ms UTC 01:49 PVG 09:49 LAX 18:49 JFK 21:49
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86