为什么gc()不能释放内存?

use*_*417 57 garbage-collection r

我在具有64 GB RAMWindows 64位计算机上运行模拟.内存使用率达到55%,在完成模拟运行后,我删除了工作空间中的所有对象,然后是a .rm(list=ls())double gc()

我认为这会为下一次模拟运行释放足够的内存,但实际内存使用率仅下降1%.咨询了很多不同的论坛我找不到令人满意的解释,只有模糊的评论如:

"根据您的操作系统,释放的内存可能不会返回到操作系统,而是保留在进程空间中."

我想找到以下信息:

  • 1)哪个操作系统和哪些条件释放内存不会返回给操作系统,以及
  • 2)如果有任何其他补救措施而不是关闭R并再次启动它以进行下一次模拟运行?

sds*_*sds 28

R垃圾收集器在以下(不那么)微妙的方式不完美:它没有移动物体(即,它不紧凑的,因为它与交互的方式存储)C库.(一些其他语言/实现从这个挨得过,但其他人,尽管也有与之交互C,管理有压缩代GC这也不会存在这个问题).

这意味着如果轮流分配小块内存然后被丢弃而更大的块用于更永久的对象(这是执行字符串/正则表达式处理时的常见情况),那么您的内存会变得碎片化,垃圾收集器无法做任何事情它:内存被释放,但由于空闲块太短,无法重复使用.

解决问题的唯一方法是保存所需的对象,重新启动R并重新加载对象.

由于你正在做rm(list=ls()),即你不需要任何对象,你不需要保存和重新加载任何东西,因此,在你的情况下,解决方案正是你想要避免的 - 重新启动R.

PS.垃圾收集是一个非常重要的主题.例如,Ruby在20年内使用了5种(!)不同的GC算法.Java GC并不糟糕,因为Sun/OracleIBM在各自的GC实现上花了很多程序员年.另一方面,R和Python有糟糕的GC - 因为没有人费心去投入必要的人年 - 而且它们很受欢迎.那更糟 -对你来说更好.

  • @AlexanderHanysz:完全没有.唉,可靠地清理内存的唯一方法是重新启动R.散布释放内存的对象可能是工作环境的一部分,不会被`rm(list = ls())`删除. (3认同)
  • "解决问题的唯一方法是保存所需的对象,重新启动R,然后重新加载对象." 我认为关于R的说得不好 (3认同)
  • @skan:R 非常擅长它的工作,并且它的 GC 被替换的可能性极小。Python 的 GC 也很糟糕(它是 refcounting!)我对 Julia 一无所知。一般来说,GC对于像R这样的研究平台来说是次要的。对于生产中经常使用的Python来说更重要,但我认为可能会发生变化。 (2认同)
  • 很好的答案。它比你暗示的更极端:“许多程序员年”是一种惊人的轻描淡写(实际数字是几个世纪以来),并且他们的 GC *仍然* 在某些情况下很糟糕。 (2认同)

Iva*_*lik 23

你如何检查内存使用情况?通常,虚拟机会分配一些用于存储其数据的内存块.部分分配可能未使用并标记为免费.GC做的是发现未从其他任何地方引用的数据并将相应的内存块标记为未使用,这并不意味着该内存被释放到OS.从VM的角度来看,现在有更多的可用内存可用于进一步计算.

正如其他人所问,您是否遇到过内存错误?如果没有,那就没什么好担心的了.

编辑: 应该是足够的了解如何内存分配和垃圾收集工作R.

从第一份文件:

有时会尝试将未使用的页面释放回操作系统.当页面被释放时,保留了等于R_MaxKeepFrac的每个类的分配节点数的许多空闲节点.发布不需要满足此要求的页面.每个R_PageReleaseFreq 1级或2级集合都会尝试释放页面.

EDIT2:

要查看已用内存,请尝试运行gc()并将verbose设置为TRUE:

gc(verbose=T)
Run Code Online (Sandbox Code Playgroud)

这是一个内存中包含10'000'000个整数数组的结果:

Garbage collection 9 = 1+0+8 (level 2) ... 
10.7 Mbytes of cons cells used (49%)
40.6 Mbytes of vectors used (72%)
          used (Mb) gc trigger (Mb) max used (Mb)
Ncells  198838 10.7     407500 21.8   350000 18.7
Vcells 5311050 40.6    7421749 56.7  5311504 40.6
Run Code Online (Sandbox Code Playgroud)

这是在丢弃对它的引用之后:

Garbage collection 10 = 1+0+9 (level 2) ... 
10.7 Mbytes of cons cells used (49%)
2.4 Mbytes of vectors used (5%)
         used (Mb) gc trigger (Mb) max used (Mb)
Ncells 198821 10.7     407500 21.8   350000 18.7
Vcells 310987  2.4    5937399 45.3  5311504 40.6
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,Vcells使用的内存从40.6Mb下降到2.4Mb.