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

golang 在 Windows 下,网络 io 资源消耗似乎比比 Linux 高一些

  •  
  •   seWindows · 27 天前 · 2511 次点击
    有一个网络处理程序,大量小包吞吐,直接使用 goroute 开新协程后 io.copy 直接处理后续接口。go 确实写的很快。

    go1.23+编译

    Linux 虚拟机下跑满虚拟网卡 100M 后,cpu 占用 4%,换成 win 下跑满虚拟网卡 100M 大约 14%。除了 cpu 占用高一些外,其他并没有明显差异,而且两者网络延迟差不多,并且都能跑满。


    cpu 性能是瓶颈,但是感觉现在不重要。毕竟现在 cpu 性能普遍过剩。

    而且 Windows 毕竟大多数是客户端,把性能负担加到用户,其实也是很普遍的行为了。比如著名的 electron 框架。
    17 条回复    2025-08-09 00:47:48 +08:00
    ysc3839
        1
    ysc3839  
       27 天前
    14%是怎么看的?任务管理器“进程”那里是不准的,要看“详细信息”。
    ebi5oowiiy1llo
        2
    ebi5oowiiy1llo  
       27 天前 via Android
    win 大多数场景性能都略差于 linux ,一方面是微内核,另一方面 linux 全球开发者帮它优化,windows 这时候还在写 w11 bug
    Mithril
        3
    Mithril  
       27 天前
    没记错的话,Go 的 io.copy 在 Linux 上用的应该是 epoll ,单纯比较极限性能,Windows 上的 IOCP 应该和它差不多,甚至稍好一些。

    如果是比较 Windows 和 Linux 的网络性能的话,最好是直接用系统原生的 API ,在物理网卡上跑。

    但其实绝大多数情况你压根用不着这么极限的网络性能,有那时间和精力压榨这么点性能不如直接升级硬件。
    DefoliationM
        4
    DefoliationM  
       27 天前 via Android
    win 的 io 性能本来就差。
    wuruxu
        5
    wuruxu  
       27 天前
    win10 讲性能,没有比 linux 好的,就是能跑的软件多
    liuhan907
        6
    liuhan907  
       26 天前
    Go 没怎么太关心在 Windows 上的性能。以及 IOCP 的模型和 epoll 的模型不兼容,Go 选择了照顾 Linux 环境而加重了 Windows 上的开销。论及纯粹的性能来说 IOCP 比 epoll 强,要到 io_uring 这个接口出现才算打平。
    NightFlame
        7
    NightFlame  
       26 天前
    @ysc3839 为什么不准
    kkocdko
        8
    kkocdko  
       26 天前
    @Mithril Go 的 io.Copy 在允许的情况下会 splice ,零拷贝。我不清楚楼主的场景是不是用上了。
    seWindows
        9
    seWindows  
    OP
       26 天前
    @Mithril
    @liuhan907

    看了一下源代码,golang 会在每次 fd 操作时进行其余的句柄分离,以确保线程安全。看上去会从原始 Socket 从 IOCP 上解绑。

    然后再 RawControl 与 dupSocket 调用获取新句柄,最后再把 newWindowsFile 包装成 *os.File 。
    其他复杂的我没有深入追踪,可能和这个有关。每次分离应该都要进入内核态

    https://github.com/golang/go/blob/master/src/net/fd_windows.go#L243

    如果直接在同一个句柄上循环使用 WSARecv/WSASend 性能应该好得多 。但是对于现在 cpu 性能来说,应该是可以接受的,只会多占用一点 cpu
    ysc3839
        10
    ysc3839  
       26 天前 via Android   ❤️ 1
    @NightFlame 因为任务管理器会用实际的 CPU 使用率乘以 CPU 频率倍数。假如实际的使用率是 10%,CPU 基准频率是 2GHz ,实际频率是 4GHz ,那显示的使用率会是 20%。
    NightFlame
        11
    NightFlame  
       26 天前
    @ysc3839 #10 懂了,详细信息里的 CPU 列的数字怎么理解,大部分是 00 ,系统空闲进程是 90 ,这是 90%的意思吗
    wwqgtxx
        12
    wwqgtxx  
       26 天前
    @seWindows 正常的 Read 和 Write 调用根本不会走到那个 dup 的
    如果你的说的是两个*net.TCPConn 直接 io.Copy 拷贝的速度,那单纯就是 Linux 下会调用 splice 而 windows 下没这项优化
    seWindows
        13
    seWindows  
    OP
       26 天前
    @wwqgtxx 也许是这样,我只是粗略的看了一下。可能确实是 go 在 linux 下有比 Windows 的优化。
    seWindows
        14
    seWindows  
    OP
       26 天前
    @ysc3839 感谢提醒,14%是在进程栏看的,“详细信息”确实只有一半。
    wwqgtxx
        15
    wwqgtxx  
       26 天前
    你所看到的所有分离 handle 操作本质上都和这个 issue 有关
    https://github.com/golang/go/issues/19098
    net 库中正常的 Read 和 Write 以及 ReadFrom/WriteTo 接口实际上都进入了 internal/poll 中使用 execIO 函数调用 iocp 完成,并不会封装成*os.File
    opengg
        16
    opengg  
       26 天前
    Windows 是二等公民
    ysc3839
        17
    ysc3839  
       26 天前
    @NightFlame 是的,详细信息里 CPU 那栏就是 CPU 使用率的百分比
    关于   ·   帮助文档   ·   自助推广系统   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1855 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 00:00 · PVG 08:00 · LAX 17:00 · JFK 20:00
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.