是不是 gc 过程都会导致应用暂停

2022-07-01 09:37:58 +08:00
 plko345

有 gc 的语言在 gc 过程中是不是都会暂停,这种暂停在什么情况下会难以接受。

如 c c++ rust ,他们在回收内存的过程中会暂停吗?

6396 次点击
所在节点    程序员
34 条回复
cubecube
2022-07-01 09:43:17 +08:00
有 gc 基本都会有暂停,但是也存在一些消除暂停的 GC 算法,比如商业的 Zing JVM 。
c rust 不暂停主要是因为自己管内存,用完及时释放了。
ql562482472
2022-07-01 09:52:51 +08:00
我记得 java 中 stop the world 是因为它有一刻要遍历所有的对象找到 Root 对象吧
如果没有 root 对象的设计,应该就不会全部暂停
liaohongxing
2022-07-01 09:55:49 +08:00
go 的 gc 已改进到停顿 1ms, 非极端场景基本可忽略 , 到了 1ms 都忍受不了,可以换 c/c++/rust
zmqiang
2022-07-01 09:56:43 +08:00
我印象中,需要暂停的 gc ,是因为运行时需要获取当前内存的使用情况,所以程序逻辑必须暂停。

c c++是手动释放内存的,运行时不参与,所以不存在暂停,各自管各自的就行。并且不需要扫描,哪些内存需要释放是交给程序员决定的

rust 不是很了解,但印象中好像也是不存在 gc 的

go 最新 gc 算法,可以基本避免程序暂停的,是可以实现运行时和程序逻辑并行运行的
bruce0
2022-07-01 10:01:26 +08:00
go 现在只会在开启和关闭内存屏障的时刻会暂停一下, 基本在 1ms 左右, 性能基本可以忽略不计了,
C++智能指针 通过引用计数器做的, 没有 GC 不会有暂停的问题,
rust 不了解, 好像是在编译时期计算得到生命周期 实现内存管理的, 也没有 GC 不会有暂停问题
nicebird
2022-07-01 10:05:03 +08:00
c\c++\rust 手动管理,按需释放。做的一般的,释放过程被离散开了,不会暂停。做的差的,集中释放大量内存,一样会卡住。
Kould
2022-07-01 10:09:48 +08:00
现有的所有垃圾收集算法实际上并不能避免 STW ,而现在只能做到尽可能减少 STW 时间,而有些像 ZGC 这样的就是主打低延迟的垃圾收集器。而 STW 主要影响那种尾部延迟(tail latencies ,多个请求下,响应最慢的请求延迟)比较敏感的服务。ddia 中有这样描述延迟影响的一段话:
“响应时间的高百分位点(也称为 尾部延迟,即 tail latencies )非常重要,因为它们直接影响用户的服务体验。例如亚马逊在描述内部服务的响应时间要求时是以 99.9 百分位点为准,即使它只影响一千个请求中的一个。这是因为请求响应最慢的客户往往也是数据最多的客户,也可以说是最有价值的客户 —— 因为他们掏钱了 [19] 。保证网站响应迅速对于保持客户的满意度非常重要,亚马逊观察到:响应时间增加 100 毫秒,销售量就减少 1% [20] ;而另一些报告说:慢 1 秒钟会让客户满意度指标减少 16% [21 ,22] 。”
而类似 c c++ rust 则属于没有 gc 的语言,需要开发者自己控制内存释放,所以微观来说回收内存会导致指令级的停顿,但是因为开发者有着对对象清晰的结构梳理,在使用得当的情况下则不会导致类似 GC 这样相对来说集中且漫长的延迟(除非你自己整了一套 gc 机制)。
Suddoo
2022-07-01 10:11:12 +08:00
JVM 的 gc 暂停时间已经控制在 1ms 以内了、而且也没有什么乱七八糟的参数让二把手们去“调优”了,这个时间对于大部分场景都可以接受,又不是造航天飞机

牺牲了 1ms 的暂停时间,换来开发效率上质的提升,比手动管理内存的语言,降低了手动释放内存的心智负担
cppc
2022-07-01 10:13:32 +08:00
如果你问的 GC 是指这个 https://en.wikipedia.org/wiki/Garbage_collection_(computer_science)

那么 c c++ rust 不存在 GC 这一说,这活得程序员自己干,换句话说,内存的申请、释放在程序代码里体现得清清楚楚。
libook
2022-07-01 10:22:42 +08:00
按我自己的话来说,编程语言视运行时内存管理模式可以划分有 GC 和无 GC 两种,有 GC 就是运行时会自动检测无用的内存数据并释放掉,无 GC 就是开发者决定哪些内存数据什么时候释放掉,不管是显式释放( C 、C++),还是隐式释放( Rust )。

GC 机制本身不一定非要暂停应用,这取决于使用的 GC 算法。
比如一种算法是先标记可达对象,再删除没被标记的对象,那么如果不暂停应用的话,可能在标记和删除操作之间产生了新对象,而这些新对象还没被标记,而删除策略是删除所有未标记对象,就会造成误删。

很多有 GC 机制的语言同时支持多种 GC 算法,具体可以了解一下是不是每种都会暂停应用。
iosyyy
2022-07-01 11:15:01 +08:00
@cubecube 并不是是因为清除的时候涉及移动对象位置以及对象本身的变化
hxtheone
2022-07-01 11:30:53 +08:00
遍历和标记都可以并发操作, 主要是一些 gc 实现里内存压缩这一步, 在清理碎片的过程会导致引用的内存地址变动, 这里的 stw 是省不了的, 要不就换 gc 算法, 要不就不用 gc 自己管理
ksco
2022-07-01 12:28:50 +08:00
推荐阅读此书:垃圾回收算法手册:自动内存管理的艺术
https://book.douban.com/subject/26740958/

字字珠玑。
jhdxr
2022-07-01 12:44:29 +08:00
时代的变迁啊,以前讨论 GC 的时候,拿出来说的基本上都是 java 。现在默认都成 go 了么?
duke807
2022-07-01 13:23:34 +08:00
譬如需要確保實時性的任務,preempt-rt linux 環境,用戶空間寫 c 程序,內存是要在初始化的時候申請好,中途不能釋放內存,也不能申請內存,以保證實時性。
agagega
2022-07-01 13:30:21 +08:00
C++/Rust 释放内存时不会有你想象的那种「暂停」,但如果内存分配器做得不好的话,运行期间也会有大量零散的内存释放,所以有人说这种情况下无 GC 的性能反而不如 GC
12101111
2022-07-01 14:22:28 +08:00
延迟和吞吐量是两回事, 好的 gc 能做到高的吞吐量, 但是 1ms 的延迟说实在还是很高的, 原子引用计数基本上都是纳秒级别的(几百个时钟周期)
yyysuo
2022-07-01 14:36:53 +08:00
高潮的过程中会暂停?
VictorJing94
2022-07-01 15:09:04 +08:00
实时性要求高的时候..........弄 C#遇到过,偶尔程序会卡一下,后面排查发现有人在自旋代码块里加了一句 GC.Collect.......
clrss
2022-07-01 15:13:16 +08:00
@yyysuo 叉出去.jpg

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

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

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

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

© 2021 V2EX