Suddoo
JVM 的 gc 暂停时间已经控制在 1ms 以内了、而且也没有什么乱七八糟的参数让二把手们去“调优”了,这个时间对于大部分场景都可以接受,又不是造航天飞机
牺牲了 1ms 的暂停时间,换来开发效率上质的提升,比手动管理内存的语言,降低了手动释放内存的心智负担
cppc
如果你问的 GC 是指这个 https://en.wikipedia.org/wiki/Garbage_collection_(computer_science)
那么 c c++ rust 不存在 GC 这一说,这活得程序员自己干,换句话说,内存的申请、释放在程序代码里体现得清清楚楚。
libook
按我自己的话来说,编程语言视运行时内存管理模式可以划分有 GC 和无 GC 两种,有 GC 就是运行时会自动检测无用的内存数据并释放掉,无 GC 就是开发者决定哪些内存数据什么时候释放掉,不管是显式释放( C 、C++),还是隐式释放( Rust )。
GC 机制本身不一定非要暂停应用,这取决于使用的 GC 算法。
比如一种算法是先标记可达对象,再删除没被标记的对象,那么如果不暂停应用的话,可能在标记和删除操作之间产生了新对象,而这些新对象还没被标记,而删除策略是删除所有未标记对象,就会造成误删。
很多有 GC 机制的语言同时支持多种 GC 算法,具体可以了解一下是不是每种都会暂停应用。
iosyyy
cubecube 并不是是因为清除的时候涉及移动对象位置以及对象本身的变化
hxtheone
遍历和标记都可以并发操作, 主要是一些 gc 实现里内存压缩这一步, 在清理碎片的过程会导致引用的内存地址变动, 这里的 stw 是省不了的, 要不就换 gc 算法, 要不就不用 gc 自己管理
ksco
推荐阅读此书:垃圾回收算法手册:自动内存管理的艺术
https://book.douban.com/subject/26740958/
字字珠玑。
jhdxr
时代的变迁啊,以前讨论 GC 的时候,拿出来说的基本上都是 java 。现在默认都成 go 了么?
duke807
譬如需要確保實時性的任務,preempt-rt linux 環境,用戶空間寫 c 程序,內存是要在初始化的時候申請好,中途不能釋放內存,也不能申請內存,以保證實時性。
agagega
C++/Rust 释放内存时不会有你想象的那种「暂停」,但如果内存分配器做得不好的话,运行期间也会有大量零散的内存释放,所以有人说这种情况下无 GC 的性能反而不如 GC
12101111
延迟和吞吐量是两回事, 好的 gc 能做到高的吞吐量, 但是 1ms 的延迟说实在还是很高的, 原子引用计数基本上都是纳秒级别的(几百个时钟周期)
sujin190
12101111 #17 原子引用计数单个确实不高,但是明显你忽略了引用计数需要的操作数可是远远超过了 GC 的,引用计数只是不会导致全局暂停延时而已,并不能降低整体延时,甚至是增加延时的
VictorJing94
实时性要求高的时候..........弄 C#遇到过,偶尔程序会卡一下,后面排查发现有人在自旋代码块里加了一句 GC.Collect.......
dqzcwxb
JDK 16 中的 ZGC:平均暂停时间 0.05 毫秒 - Glavo 的文章 - 知乎
https://zhuanlan.zhihu.com/p/359249269
0.05 毫秒能满足你的要求吗
aptupdate
dqzcwxb 所以升级到 JDK16 或 17 可以免费获取很多性能,奈何市面上还是一手 JDK8 打天下。
secondwtq
”进程”会暂时呆住,但是”应用”不一定。这俩并不是同一个概念
其实 Tracing GC 影响的事所有和进行 GC 的堆相关的对象,你在一个进程里放多个 GC 堆隔离起来,也能避免进程暂停
RAII 也有类似的问题,简单粗暴的 RAII 如果出现一个对象拖着一大坨对象,出作用域的时候有得你回收的
0x2CA
gc 是有不同的算法的,常见的有 Reference Counting ,Mark Sweep ,Copy Collection 等等,你可以参考这个文章 https://zhuanlan.zhihu.com/p/54111851 ,了解大概
FrankHB
不一定,现代的一些 GC 实现可以并发回收,暂停个别线程而不是整个进程。实用上(暂停时间能保证短至分时系统的个别时间片粒度)只影响 GC 线程而完全避免阻塞应用线程的实现很少,像 Asul C4 。代价是感人的内存使用率。
C/C++之类用全局堆之类实现的自由存储一样不能完全避免对全局共享的分配器内部管理数据结构加锁而可能暂停,但是任何靠谱的实现中这个暂停相对几乎所有 GC 都非常短而基本可以忽略。一些实现如 snmalloc 在同一个线程中的分配和释放可以完全不暂停其它线程。用户实现的只对特定线程可用的分配器可以不影响其它线程。
以上 GC 专指全局 tracing GC 。多实例 GC 堆和引用计数对整个应用的影响在此都可以视同后者。
当然如果程序是单线程的,那么不管是 GC 还是确定性分配器都会直接阻塞,因为没什么实现无聊到在释放算法里实现分时多任务。
FrankHB
Kould 即使使用得当,不限深度的嵌套数据结构集中释放也很容易出现高延迟的问题。(这不属于使用不当,因为语言允许轻易地构造这种对象。)实际上不容易观察到类似的问题,是因为在此之前,大多数 naive 实现在递归调用释放资源的例程中就直接爆栈了(