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

2019-07-29 11:09:47 +08:00
 abcbuzhiming
同样是带有 GC 的语言,Go 的内存占用也太低了点,国外的测试里,同样的功能,Java 都吃到接近 1GB 内存的时候,Go 就十几 MB 的占用;就算不和“家里开矿才能用”的 Java 比,和新锐的 dotnet core 比也有好几倍的差距。我没想明白的是,都是带 GC 的语言,凭什么 Go 就能占这么低的内存?
13489 次点击
所在节点    Go 编程语言
37 条回复
2kCS5c0b0ITXE5k2
2019-07-29 11:12:38 +08:00
go 编译时直接转到机器码
neoblackcap
2019-07-29 11:18:00 +08:00
jit 需要内存。至于相同的功能这个说法我表示怀疑。
GC 其实跟内存用多少关系不大。
hoyixi
2019-07-29 11:18:58 +08:00
java 首先得要个 JVM
chenqh
2019-07-29 11:20:34 +08:00
蛇框架?
chenqh
2019-07-29 11:20:44 +08:00
什么框架?
rrfeng
2019-07-29 11:23:06 +08:00
1. JVM 本身,带 VM 的语言天然就有开销
2. 设计原因,一个整数类型 Java 里包装了多少层?
3. 历史包袱,同样功能,Java 可能引入了很多实际上用不到的代码。而 Go 比较年轻,自带库都比较精简。
micean
2019-07-29 11:33:19 +08:00
啥测试? java 也没这么夸张吧
reus
2019-07-29 11:34:32 +08:00
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
2019-07-29 12:04:21 +08:00
Java 特性那么多,runtime 肯定比 go 费时费内存啊。而且 java 还有层 jvm。java 还有它那........个无穷无尽的调用。。。
LokiSharp
2019-07-29 12:10:30 +08:00
你确定 Go 写得内个东西功能和 Java 的一样?
lizhuoli
2019-07-29 12:13:41 +08:00
GC 和内存占用大小关系不大,主要是影响分配和回收的性能。对内存影响大的主要是 JVM,Go 压根没有 VM,不需要这一层来做额外的解释和执行内存占用。这是两个东西
abcbuzhiming
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
2019-07-29 12:43:35 +08:00
@abcbuzhiming #12 看起来内存占用差不多啊 Java 虚拟机初始化了差不多 30-40MB,你看 Go CPU 占用都比 Java 高。感觉是默认的 GC 频率比较高吧
abcbuzhiming
2019-07-29 12:47:01 +08:00
@LokiSharp 你确定你看过了,那个连接里出了 reverse 这一项,其它的项目 java 的内存占用起码都是 go 的几倍起
realpg
2019-07-29 12:54:30 +08:00
不论什么 JIT 的问题
golang 出来的是原生程序,还是静态链接的
还是跟 C/C++ 静态链接的进行一下对比吧

且不说那些技术的东西

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

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

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

go 和 java 的语言设计思路不一样,go 解决的是谷歌这种级别的大规模工程问题,java 解决的是应用跨平台的问题,两者不是对立关系,哪个适合就用哪个。
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
2019-07-29 13:04:41 +08:00
这两个例子。。。Java 的内存使用是 Go 翻倍但是运行时间却是 Go 的三分之一,综合算下来资源使用并不比 Go 高
rrfeng
2019-07-29 13:09:43 +08:00
楼上优化 Java 达到了 native c++ 代码的速度:请问 c++ 是与你同等领域经验的工程师优化过的吗?
reus
2019-07-29 13:16:21 +08:00
@LokiSharp regex-redux 慢,是因为用到了 cgo。binary trees 慢,是因为 go 的 GC 比 java 的更频繁,消耗 cpu 更多。基本上 GC 多的程序,go 都比 java 慢,因为 go 偏向低延迟,而不是高吞吐

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/587073

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX