go - C 代码是否享受 Go GC 的碎片预防策略?

标签 go garbage-collection swig cgo virtual-address-space

<分区>

更正了错误的暗示:

Golang 的 GC 执行虚拟地址空间碎片整理碎片预防策略,这使程序能够运行很长时间(如果不是永远的话)。

但似乎 C 代码(cgo 或 SWIG)无法更新它的内存指针,以防它们被移动到别处。从这些策略中获益。

  1. 这是真的吗? C 代码不会受益于 Golang 的虚拟地址空间 碎片整理 碎片预防,最终得到碎片吗?

  2. 如果那是假的,怎么办?

  3. 此外,C 代码加载的任何 DLL 代码(例如 Windows DLL)会怎样?

(问题已更新以纠正我的错误假设)

最佳答案

恐怕您在这里可能会混淆多个层面的事情。

首先,在生产级 Go 代码中调用 C 是通常从一开始就不行的:它很慢;和进行系统调用一样慢——在大多数情况下,它实际上是作为系统调用工作的:需要从 Go 堆栈切换到 C 堆栈,并让 OS 线程恰好正在执行 Go 代码cgo 调用被锁定到该线程,即使 C 端发生阻塞。

这并不是说您必须避免调用 C,但这意味着您需要预先考虑这一点并进行衡量。可能正在设置一个工作 goroutines 池以在其上展开找出需要进行 C 调用的任务。

其次,您对内存的担忧可能是没有根据的;让我解释一下。

碎片化虚拟内存在现代系统上应该不是问题 通常用于运行 Go 程序(我指的是 amd64 之类的)。 这几乎是因为分配虚拟内存不会强制操作系统 实际分配物理内存页——后者只发生 当虚拟内存被使用时(也就是说,在一个地址访问 碰巧指向分配的虚拟内存区域)。 所以,不管你愿意与否,你确实有物理内存碎片问题 无论如何,它正在得到解决 在操作系统和 CPU 级别使用多层地址转换 表(和 TLB 缓存)。

第三,您似乎落入了推测的常见陷阱 事情将如何在负载下执行而不是编写一个高度简化的 模型程序并检查它在估计产量下的表现 加载。也就是说,您认为分配 C 内存时会出现问题 然后幻想整个事情都行不通。

我会说你的担心是没有根据的——考虑到产量 用 C 和 C++ 编写并在硬核负载下工作的代码。

最后,C 和 C++ 程序员踏上了通往高性能的道路 很久以前的内存管理。一个典型的解决方案是使用自定义 显示最多的对象的池分配器 典型负载下的分配/解除分配搅动。通过这种方法, 在 C 端分配的内存在整个生命周期内基本稳定 你的程序。

长话短说

编写一个模型程序,将估计的负载放在上面,看看它的行为如何。 然后分析,内存有什么问题,如果有的话,以及 然后才开始攻击他们。

关于go - C 代码是否享受 Go GC 的碎片预防策略?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49694558/

相关文章:

delegates - c++/cli 终结器中免费 GCHandle 的最佳实践

java - CMS Old GC触发的阈值是多少

python - 如何在 python 中使用枚举?

python - 如何用 C++ 扩展 Python?

c++ - 返回 const char*;静电有多难看?

json解码错误

go - 为什么 log.Printf() 不打印?

go - 为什么使用 _ 空白标识符的范围迭代会产生不同的值

mongodb - Mongodb 的 Golang mgo 聚合

java - 在调查内存泄漏时要寻找哪一代?