Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么CGO_ENABLE会对虚拟内存产生如此大的影响?_Go - Fatal编程技术网

为什么CGO_ENABLE会对虚拟内存产生如此大的影响?

为什么CGO_ENABLE会对虚拟内存产生如此大的影响?,go,Go,我有一个写在Golang上的小守护进程,它在循环中工作并做一些事情。我发现,当使用CGO_ENABLE=1或CGO_ENABLE=0编译守护进程时,守护进程的行为会有所不同。例如,当CGO_ENABLE=1(默认值)时,程序的VSZ在短时间内(一小时内)膨胀到1-2GB。启用CGO_=0时,VSZ在长时间内(几天内)是相同的。请看下面的数字: CGO_ENABLED=1(守护进程已工作5分钟) CGO_ENABLED=0(守护进程已工作约30小时) 守护进程不使用依赖于CGO的包或函数。其他Go

我有一个写在Golang上的小守护进程,它在循环中工作并做一些事情。我发现,当使用CGO_ENABLE=1或CGO_ENABLE=0编译守护进程时,守护进程的行为会有所不同。例如,当CGO_ENABLE=1(默认值)时,程序的VSZ在短时间内(一小时内)膨胀到1-2GB。启用CGO_=0时,VSZ在长时间内(几天内)是相同的。请看下面的数字:

CGO_ENABLED=1(守护进程已工作5分钟)

CGO_ENABLED=0(守护进程已工作约30小时)

守护进程不使用依赖于CGO的包或函数。其他Go编写的程序也表现出同样的行为。我知道VSZ和RSS之间的区别,我很感兴趣,这种行为的本质是什么?为什么使用CGO_ENABLED=1编译的程序要求从内核提供这么多内存


我希望答案不是“别担心,VSZ只是一个虚拟内存,实际上它不被进程使用”这样的形式

您可能知道,“reference”Go实现(历史上称为“gc”;可从下载)的编译器默认生成静态链接的二进制文件。这意味着,这些二进制文件只依赖于操作系统内核提供的所谓“系统调用”,而不依赖于操作系统(或第三方)提供的任何共享库

在基于Linux的平台上,这并非完全正确:在默认设置(基于Linux for Linux构建,即不交叉编译)中,生成的二进制文件实际上与
libc
并使用
libpthread
(间接地,通过
libc

这种“扭曲”来自Go标准库必须与操作系统交互的两个需求:

  • DNS解析,
    net
    包需要此解析
  • 用户和组查找,这是
    os
    包所需要的
  • 这里的问题有两个方面:

    • Linux本身(即内核,而不是整个操作系统)不提供任何执行这些任务的方法

    • 从永远以来,任何典型的类UNIX系统都使用一种称为“NSS”的特殊工具来提供这两种任务, 哪一个是“名称服务开关”

      NSS提供可插拔的模块,可用于 作为提供特定类型查询的数据库:DNS、用户/组数据库等(如“服务”的知名名称等)。一个被认为是相当普遍的例子 用户/组数据库的非标准提供程序是本地数据库 与LDAP服务器联系的服务

    在典型的基于GNU/Linux的操作系统上,NSS由
    libc
    (在不太典型的系统上,它可能由 单独的共享库,但变化不大)

    因为,
    libc
    是一个相当稳定的 库的API(它甚至提供了版本符号 作为未来的证明),Go作者正确地决定,针对
    libc
    链接以导入符号的最小子集(主要是
    getaddrinfo
    getnameinfo
    getpwnam_r
    等)是可以的 默认情况下,99%的情况下都是安全的, 如果不是,那些必须处理这些案件的人通常 我知道该怎么办

    因此,默认情况下启用了
    cgo
    ,并用于使用NSS实现这些查找

    如果禁用了
    cgo
    ,则Go编译器将改为在其自身中链接 回退实现,尝试模仿 完整的NSS实现(即解析
    /etc/resolv.conf
    并使用其中的信息直接查询此处列出的DNS服务器;解析
    /etc/passwd
    /etc/group
    以服务于用户/组数据库查询)

    如你所见,在defult的案例中

    • libc
      被映射到,并且
    • 它被初始化并使用一些内存来满足自己的需要- 例如NSS调用返回的数据的明显缓存
    相反,在禁用
    cgo
    的情况下,上述两种情况不会发生。您有更多静态链接的stdlib代码,但就RSS的总体累积使用量而言,默认情况似乎仅优于后者

    考虑研究 为了增加乐趣;-)



    不要与Mozilla混淆。

    您可以比较/proc/$pid/maps来找出答案。VSZ不是“内核提供的内存”。它毕竟是虚拟的,包括交换内存、与其他程序共享的内存、内存映射文件等。同样,/proc/$pid/maps有一个故障。@Peter,谢谢你,但是我上面提到了我知道什么是VSZ。也许我用了一点不正确的描述。此外,地图文件是一个众所周知的为我。我问过,为什么启用CGO_会影响程序所描述的行为,而不是VSZ。你是在Linux上尝试这个吗?是的,在Linux上。谢谢,听起来很合理。还有,关于
    $ grep -E 'VmSize|VmRSS' /proc/14916/status
    VmSize:    1084052 kB
    VmRSS:       12524 kB
    
    $ grep -E 'VmSize|VmRSS' /proc/15160/status
    VmSize:    110232 kB
    VmRSS:       9756 kB