是不是 gc 过程都会导致应用暂停 - V2EX
2022-7-1 19:22:16 Author: v2ex.com(查看原文) 阅读量:32 收藏

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

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

25 条回复    2022-07-01 18:48:09 +08:00

cubecube

1

cubecube      9 小时 38 分钟前

有 gc 基本都会有暂停,但是也存在一些消除暂停的 GC 算法,比如商业的 Zing JVM 。
c rust 不暂停主要是因为自己管内存,用完及时释放了。

ql562482472

2

ql562482472      9 小时 29 分钟前

我记得 java 中 stop the world 是因为它有一刻要遍历所有的对象找到 Root 对象吧
如果没有 root 对象的设计,应该就不会全部暂停

liaohongxing

3

liaohongxing      9 小时 26 分钟前

go 的 gc 已改进到停顿 1ms, 非极端场景基本可忽略 , 到了 1ms 都忍受不了,可以换 c/c++/rust

zmqiang

4

zmqiang      9 小时 25 分钟前

我印象中,需要暂停的 gc ,是因为运行时需要获取当前内存的使用情况,所以程序逻辑必须暂停。

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

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

go 最新 gc 算法,可以基本避免程序暂停的,是可以实现运行时和程序逻辑并行运行的

bruce0

5

bruce0      9 小时 20 分钟前

go 现在只会在开启和关闭内存屏障的时刻会暂停一下, 基本在 1ms 左右, 性能基本可以忽略不计了,
C++智能指针 通过引用计数器做的, 没有 GC 不会有暂停的问题,
rust 不了解, 好像是在编译时期计算得到生命周期 实现内存管理的, 也没有 GC 不会有暂停问题

nicebird

6

nicebird      9 小时 17 分钟前

c\c++\rust 手动管理,按需释放。做的一般的,释放过程被离散开了,不会暂停。做的差的,集中释放大量内存,一样会卡住。

Kould

7

Kould      9 小时 12 分钟前   ❤️ 1

现有的所有垃圾收集算法实际上并不能避免 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

8

Suddoo      9 小时 11 分钟前 via iPhone   ❤️ 2

JVM 的 gc 暂停时间已经控制在 1ms 以内了、而且也没有什么乱七八糟的参数让二把手们去“调优”了,这个时间对于大部分场景都可以接受,又不是造航天飞机

牺牲了 1ms 的暂停时间,换来开发效率上质的提升,比手动管理内存的语言,降低了手动释放内存的心智负担

libook

10

libook      8 小时 59 分钟前

按我自己的话来说,编程语言视运行时内存管理模式可以划分有 GC 和无 GC 两种,有 GC 就是运行时会自动检测无用的内存数据并释放掉,无 GC 就是开发者决定哪些内存数据什么时候释放掉,不管是显式释放( C 、C++),还是隐式释放( Rust )。

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

很多有 GC 机制的语言同时支持多种 GC 算法,具体可以了解一下是不是每种都会暂停应用。

iosyyy

11

iosyyy      8 小时 7 分钟前 via Android

@cubecube 并不是是因为清除的时候涉及移动对象位置以及对象本身的变化

hxtheone

12

hxtheone      7 小时 51 分钟前 via iPhone

遍历和标记都可以并发操作, 主要是一些 gc 实现里内存压缩这一步, 在清理碎片的过程会导致引用的内存地址变动, 这里的 stw 是省不了的, 要不就换 gc 算法, 要不就不用 gc 自己管理

jhdxr

14

jhdxr      6 小时 37 分钟前

时代的变迁啊,以前讨论 GC 的时候,拿出来说的基本上都是 java 。现在默认都成 go 了么?

duke807

15

duke807      5 小时 58 分钟前 via Android

譬如需要確保實時性的任務,preempt-rt linux 環境,用戶空間寫 c 程序,內存是要在初始化的時候申請好,中途不能釋放內存,也不能申請內存,以保證實時性。

agagega

16

agagega      5 小时 51 分钟前

C++/Rust 释放内存时不会有你想象的那种「暂停」,但如果内存分配器做得不好的话,运行期间也会有大量零散的内存释放,所以有人说这种情况下无 GC 的性能反而不如 GC

12101111

17

12101111      4 小时 59 分钟前

延迟和吞吐量是两回事, 好的 gc 能做到高的吞吐量, 但是 1ms 的延迟说实在还是很高的, 原子引用计数基本上都是纳秒级别的(几百个时钟周期)

yyysuo

18

yyysuo      4 小时 45 分钟前   ❤️ 1

高潮的过程中会暂停?

VictorJing94

19

VictorJing94      4 小时 13 分钟前

实时性要求高的时候..........弄 C#遇到过,偶尔程序会卡一下,后面排查发现有人在自旋代码块里加了一句 GC.Collect.......

aptupdate

22

aptupdate      2 小时 0 分钟前

@dqzcwxb 所以升级到 JDK16 或 17 可以免费获取很多性能,奈何市面上还是一手 JDK8 打天下。

sujin190

23

sujin190      1 小时 24 分钟前

@12101111 #17 原子引用计数单个确实不高,但是明显你忽略了引用计数需要的操作数可是远远超过了 GC 的,引用计数只是不会导致全局暂停延时而已,并不能降低整体延时,甚至是增加延时的

secondwtq

24

secondwtq      36 分钟前

”进程”会暂时呆住,但是”应用”不一定。这俩并不是同一个概念
其实 Tracing GC 影响的事所有和进行 GC 的堆相关的对象,你在一个进程里放多个 GC 堆隔离起来,也能避免进程暂停

RAII 也有类似的问题,简单粗暴的 RAII 如果出现一个对象拖着一大坨对象,出作用域的时候有得你回收的


文章来源: https://v2ex.com/t/863363#reply25
如有侵权请联系:admin#unsafe.sh