<分区>
更正了错误的暗示:
Golang 的 GC 执行虚拟地址空间碎片整理碎片预防策略,这使程序能够运行很长时间(如果不是永远的话)。
但似乎 C 代码(cgo 或 SWIG)无法更新它的内存指针,以防它们被移动到别处。从这些策略中获益。
这是真的吗? C 代码不会受益于 Golang 的虚拟地址空间
碎片整理碎片预防,最终得到碎片吗?如果那是假的,怎么办?
此外,C 代码加载的任何 DLL 代码(例如 Windows DLL)会怎样?
(问题已更新以纠正我的错误假设)
<分区>
更正了错误的暗示:
Golang 的 GC 执行虚拟地址空间碎片整理碎片预防策略,这使程序能够运行很长时间(如果不是永远的话)。
但似乎 C 代码(cgo 或 SWIG)无法更新它的内存指针,以防它们被移动到别处。从这些策略中获益。
这是真的吗? C 代码不会受益于 Golang 的虚拟地址空间 碎片整理 碎片预防,最终得到碎片吗?
如果那是假的,怎么办?
此外,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/