请教, Go 是如何实现如此夸张的低的内存占用的? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
abcbuzhiming
V2EX    Go 编程语言

请教, Go 是如何实现如此夸张的低的内存占用的?

  •  1
     
  •   abcbuzhiming 2019-07-29 11:09:47 +08:00 13964 次点击
    这是一个创建于 2266 天前的主题,其中的信息可能已经有所发展或是发生改变。
    同样是带有 GC 的语言,Go 的内存占用也太低了点,国外的测试里,同样的功能,Java 都吃到接近 1GB 内存的时候,Go 就十几 MB 的占用;就算不和“家里开矿才能用”的 Java 比,和新锐的 dotnet core 比也有好几倍的差距。我没想明白的是,都是带 GC 的语言,凭什么 Go 就能占这么低的内存?
    37 条回复    2021-07-25 15:27:27 +08:00
    2kCS5c0b0ITXE5k2
        1
    2kCS5c0b0ITXE5k2  
       2019-07-29 11:12:38 +08:00
    go 编译时直接转到机器码
    neoblackcap
        2
    neoblackcap  
       2019-07-29 11:18:00 +08:00   1
    jit 需要内存。至于相同的功能这个说法我表示怀疑。
    GC 其实跟内存用多少关系不大。
    hoyixi
        3
    hoyixi  
       2019-07-29 11:18:58 +08:00
    java 首先得要个 JVM
    chenqh
        4
    chenqh  
       2019-07-29 11:20:34 +08:00 via Android
    蛇框架?
    chenqh
        5
    chenqh  
       2019-07-29 11:20:44 +08:00 via Android
    什么框架?
    rrfeng
        6
    rrfeng  
       2019-07-29 11:23:06 +08:00
    1. JVM 本身,带 VM 的语言天然就有开销
    2. 设计原因,一个整数类型 Java 里包装了多少层?
    3. 历史包袱,同样功能,Java 可能引入了很多实际上用不到的代码。而 Go 比较年轻,自带库都比较精简。
    micean
        7
    micean  
       2019-07-29 11:33:19 +08:00
    啥测试? java 也没这么夸张吧
    reus
        8
    reus  
       2019-07-29 11:34:32 +08:00   4
    java 是虚拟机,天然就多占内存,再加上没有值类型,很多数据结构都不是紧凑布局的

    .net core 同理

    go 的自动 GC 相对于非自动 GC,多使用的内存主要是 GC bitmap,这部分是 2bit 对应堆里的 64bit,也就是 512GB 的堆全分配满的话,GC bitmap 就会有 16GB,三十二分之一的 overhead。

    另外,GC 算法不同,占内存也会不同。会复制对象的 GC,在复制过程里就需要占用额外的内存。java 的 CMS, G1 都是 copying GC。zgc 暂时不做复制。

    还有个影响因素是向 os 申请页和释放页回 os 的策略。如果虚拟机选择一开始就申请很大的内存,那占用自然高。释放慢,也会高。go 不会预先申请很大的内存,释放页也比较积极,所以内存占用相对就低。
    VDimos
        9
    VDimos  
       2019-07-29 12:04:21 +08:00 via Android
    Java 特性那么多,runtime 肯定比 go 费时费内存啊。而且 java 还有层 jvm。java 还有它那........个无穷无尽的调用。。。
    LokiSharp
        10
    LokiSharp  
       2019-07-29 12:10:30 +08:00
    你确定 Go 写得内个东西功能和 Java 的一样?
    lizhuoli
        11
    lizhuoli  
       2019-07-29 12:13:41 +08:00 via iPhone
    GC 和内存占用大小关系不大,主要是影响分配和回收的性能。对内存影响大的主要是 JVM,Go 压根没有 VM,不需要这一层来做额外的解释和执行内存占用。这是两个东西
    abcbuzhiming
        12
    abcbuzhiming  
    OP
       2019-07-29 12:32:26 +08:00
    @emeab 这个理由。。。java 和 dotnet core 是可以强行用 jit 生成机器码的,但是也没见到内存降低多少


    @hoyixi 查了一下 Go 确实没有 virtual machine,但是一个虚拟机的差别有这么大吗?

    @chenqh 无框架,看我下面给的链接

    @micean
    https://benchmarksgame-team.pages.debian.net/benchmarksgame/fastest/go.html
    看这个测试,绝大部分情况下 Go 的内存占用都吓人的低
    LokiSharp
        13
    LokiSharp  
       2019-07-29 12:43:35 +08:00
    @abcbuzhiming #12 看起来内存占用差不多啊 Java 虚拟机初始化了差不多 30-40MB,你看 Go CPU 占用都比 Java 高。感觉是默认的 GC 频率比较高吧
    abcbuzhiming
        14
    abcbuzhiming  
    OP
       2019-07-29 12:47:01 +08:00
    @LokiSharp 你确定你看过了,那个连接里出了 reverse 这一项,其它的项目 java 的内存占用起码都是 go 的几倍起
    realpg
        15
    realpg  
    PRO
       2019-07-29 12:54:30 +08:00
    不论什么 JIT 的问题
    golang 出来的是原生程序,还是静态链接的
    还是跟 C/C++ 静态链接的进行一下对比吧

    且不说那些技术的东西

    你执行一个 java 程序
    java -jar xxx
    或者
    java xxx.class

    执行的这个 java 本身就要吃很多内存不是……
    troywinter
        16
    troywinter  
       2019-07-29 12:58:14 +08:00   3
    都是 trade off,做过 jvm 的优化就知道了,没什么 go 的方式就优于 java,以大部分人写的代码那点水平,还不如让 java 虚拟机优化的性能。大多数人用 go 写出了 python 的性能。

    内存占用低,不代表性能强,只有内存的数据结构 layout 会和性能相关,和 cpu cache,tlb,llc 相关。我曾经优化过 java 服务,各种指标都大大超过了 native c++的速度,就是得益于 jvm 提供的各种优化,内存也是可以被优化的,但只有你有相对而言足够的利益驱使去做时才值得,如果内存占用在业务领域根本不重要,那有什么意义呢?

    go 和 java 的语言设计思路不一样,go 解决的是谷歌这种级别的大规模工程问题,java 解决的是应用跨平台的问题,两者不是对立关系,哪个适合就用哪个。
    LokiSharp
        17
    LokiSharp  
       2019-07-29 12:58:19 +08:00
    @abcbuzhiming #14
    regex-redux
    source secs mem gz busy cpu load
    Go
    29.20 399,668 802 61.29 71% 55% 37% 47%
    Java
    10.48 645,680 740 31.62 72% 87% 74% 68%
    binary-trees
    source secs mem gz busy cpu load
    Go
    25.25 374,780 1013 87.65 87% 88% 86% 86%
    Java
    8.28 907,060 835 27.59 86% 90% 80% 77%

    额。。。哪你咋不说 Go 的运行时间是 Java 的几倍呢。。。
    LokiSharp
        18
    LokiSharp  
       2019-07-29 13:04:41 +08:00
    这两个例子。。。Java 的内存使用是 Go 翻倍但是运行时间却是 Go 的三分之一,综合算下来资源使用并不比 Go 高
    rrfeng
        19
    rrfeng  
       2019-07-29 13:09:43 +08:00 via Android   5
    楼上优化 Java 达到了 native c++ 代码的速度:请问 c++ 是与你同等领域经验的工程师优化过的吗?
    reus
        20
    reus  
       2019-07-29 13:16:21 +08:00
    @LokiSharp regex-redux 慢,是因为用到了 cgo。binary trees 慢,是因为 go 的 GC 比 java 的更频繁,消耗 cpu 更多。基本上 GC 多的程序,go 都比 java 慢,因为 go 偏向低延迟,而不是高吞吐
    reus
        21
    reus  
       2019-07-29 13:18:26 +08:00
    @LokiSharp 看 busy 指标,这几个程序里 go 都比 java 高,就是 GC 的消耗多
    niubee1
        22
    niubee1  
       2019-07-29 13:18:44 +08:00
    JVM 你要是不弄块上 G 的内存来跑的话慢得要死
    micean
        23
    micean  
       2019-07-29 13:20:41 +08:00
    我把 binary-trees 跑了一次,不带参和带参数-Xmx500m -Xms500m,时间差不多,只是带参的 ygc 次数是不带参的 3 倍。所以只是 gc 策略问题。
    当然 java 占用内存肯定还是比 go 要多一些
    bequt
        24
    bequt  
       2019-07-29 13:21:26 +08:00
    前段时间还有个 vlang,那个内存更低
    dhssingle
        25
    dhssingle  
       2019-07-29 14:07:27 +08:00
    LokiSharp
        26
    LokiSharp  
       2019-07-29 14:07:51 +08:00 via iPhone
    @reus 为了内存占用消耗这么多 cpu 我觉得划不来
    reus
        27
    reus  
       2019-07-29 14:39:43 +08:00
    @LokiSharp 主要是还没有分代,有了分代,GC 可以少消耗一点 CPU。而且主要目的是降低延迟,而不是降低内存占用,现在 go 的 GC 的暂停时间可以低于 0.5ms
    sunwei0325
        28
    sunwei0325  
       2019-07-29 16:30:38 +08:00
    jvm 的线程栈 Xss 一般都是写死的 1-2M, go 的 goroutine 栈是动态的, 一般 2K 起
    BBCCBB
        29
    BBCCBB  
       2019-07-29 16:34:37 +08:00
    Jvm 默认会一次性申请一个大内存块, 比如你设置了-Xms1G,那就会一次性申请 1G,

    默认好像是物理内存的 3/8....
    stevenkang
        30
    stevenkang  
       2019-07-29 16:55:53 +08:00   1
    甲方:我这里有一个需求,评估一下多久能完成?

    18 岁的程序猿:最多五天,尽量三天,最快一天(分分钟开发好,年少轻狂,什么包袱都没有)
    20 岁的程序猿:算上测试这些,预计十五天(改一改 bug,修一修代码)
    25 岁的程序猿:设计、开发、测试,预计三十天(流程规范、顺便摸鱼)
    30 岁的程序猿:调研、设计、评估、开发、测试、交付,预计两个月(启动开发之前先评估成本)

    所以,你说 java 这种嵌套十八层的语言,内存需要多少呢?
    wysnylc
        31
    wysnylc  
       2019-07-29 18:59:43 +08:00
    @troywinter #16 有理有据令人信服
    dodo2012
        32
    dodo2012  
       2019-07-29 19:06:36 +08:00   1
    rust 更低,
    5200
        33
    5200  
       2019-07-29 21:06:05 +08:00
    没人注意到楼主的头像吗??
    hangszhang
        34
    hangszhang  
       2019-07-29 23:47:50 +08:00
    我是不信有这么大的差距
    wenzhoou
        35
    wenzhoou  
       2019-07-30 06:56:25 +08:00 via Android
    @5200 头像怎么放大了看?
    no1xsyzy
        36
    no1xsyzy  
       2019-07-30 11:02:12 +08:00
    @abcbuzhiming JIT 不是内存占用更高了?内存里除了运行时还需要载一个编译器,外加字节码和机器码两套码。
    zoharSoul
        37
    zoharSoul  
       2021-07-25 15:27:27 +08:00
    Java 默认是空间换时间
    golang 更倾向于小内存占用
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5852 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 30ms UTC 06:35 PVG 14:35 LAX 23:35 JFK 02:35
    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