监视R中的内存使用情况

时间:2011-10-21 23:21:09

标签: r

是否可以监控正在使用或已被R用来调用函数的内存量?例如,我有一个任意函数,例如:

smallest.sv <- function(){
  A <- matrix(rnorm(1e6), 1e3);
  mysvd <- svd(A);
  return(tail(mysvd$d, 1));
}

运行该函数只返回一个标量,但是使用了大量内存来计算函数。现在我需要进行性能基准测试。处理时间很简单:

system.time(x <- smallest.sv())

但是我还想知道这个调用需要多少内存,而不需要修改函数(它应该适用于任意函数)。有没有办法做到这一点?

编辑:澄清一下。我最感兴趣的是在函数调用期间使用的内存上限,即需要多少物理内存才能处理函数调用。在许多情况下,这远远低于我认为的分配内存总量。

4 个答案:

答案 0 :(得分:20)

R提供内存分析支持,请参阅Section 3.3 of the Writing R Extensions manual

  

3.3分析内存使用的R代码

     

在代码处理时,测量R代码中的内存使用很有用   比方便可用或内存分配更多的内存   并且复制对象是造成代码慢的原因。有三种   在R代码中描述内存使用随时间变化的方法。这三个都要求R到   已经编译了`--enable-memory-profiling',这不是   默认,但目前用于Mac OS X和Windows二进制文件   分布。由于不同的原因,所有这些都可能会产生误导。

     

在了解内存配置文件时,了解一点是很有用的   更多关于R的内存分配。看看`gc()'的结果   显示了将内存划分为用于存储内容的“Vcells”   向量和'Ncells'用于存储其他所有内容,包括所有内容   类型和长度等向量的管理开销   信息。实际上,矢量内容分为两个池。   获得小向量的存储器(默认为128字节或更少)   大块然后由R包围;更大的向量的记忆是   直接从操作系统获得。

然后再提供三个部分。

答案 1 :(得分:11)

一种选择是使用Rprof。一个简单的方法是:

Rprof(tf <- "rprof.log", memory.profiling=TRUE)

[your code]

Rprof(NULL)
summaryRprof(tf)

这将为您提供有关内存使用情况的一些信息。

答案 2 :(得分:0)

您可以使用gc获取在处理函数和命令期间使用的内存上限

smallest.sv <- function(){
  A <- matrix(rnorm(1e6), 1e3);
  mysvd <- svd(A);
  return(tail(mysvd$d, 1));
}

tt <- sum(.Internal(gc(FALSE, TRUE, TRUE))[13:14])
x <- smallest.sv()
sum(.Internal(gc(FALSE, FALSE, TRUE))[13:14]) - tt
#62 MB
rm(x)

此上限受垃圾收集的影响,因此打开gctorture将给出最低上限

tt <- sum(.Internal(gc(FALSE, TRUE, TRUE))[13:14])
gctorture(on = TRUE)
x <- smallest.sv()
gctorture(on = FALSE)
sum(.Internal(gc(FALSE, FALSE, TRUE))[13:14]) - tt
#53.7 MB

诸如RprofRprofmemprofmem::profmembench::markprofvis::profvis之类的其他工具也可以显示内存使用情况。

#Using Rprof (Enable profiling is a compile-time option: ./configure --enable_R_profiling)
gc()
Rprof("Rprof.out", memory.profiling=TRUE)
x <- smallest.sv()
Rprof(NULL)
max(summaryRprof("Rprof.out", memory="both")$by.total$mem.total)
#45.9
#Here at defined intervals the status is checked and so the result depends on if you hit the peak

#Using Rprofmem (Enable momory profiling is a compile-time option: ./configure --enable_memory_profiling)
Rprofmem("Rprofmem.out"); x <- smallest.sv(); Rprofmem(NULL) #Wen first run, there is much more in the log file
gc()
Rprofmem("Rprofmem.out")
x <- smallest.sv()
Rprofmem(NULL)
sum(as.numeric(read.table("Rprofmem.out", comment.char = ":")[,1]), na.rm=TRUE)
#88101752
#Writes out them memory amount when it is allocated

library(profmem) #uses utils::Rprofmem
gc()
total(profmem(x <- smallest.sv()))
#88101752

library(bench) #uses utils::Rprofmem
gc()
mark(x <- smallest.sv())[,"mem_alloc"]
#84MB
#Warning message:
#Some expressions had a GC in every iteration; so filtering is disabled. 

library(profvis) #uses utils::Rprof
gc()
profvis(x <- smallest.sv())
#opens a browser window where you can read under Memory -23.0 | 45.9

Rprofmem显示已累积分配的内存,并且不考虑在执行期间释放的内存。要提高Rprof达到峰值的可能性,您可以选择一个较短的时间间隔或/和/或重复该过程。

max(replicate(10, {
    gc()
    Rprof("Rprof.out", memory.profiling=TRUE, interval = runif(1,.005,0.02))
    x <- smallest.sv()
    Rprof(NULL)
    max(summaryRprof("Rprof.out", memory="both")$by.total$mem.total)
}))
#76.4

在这里,我得到的值比从gc中得到的值高,这表明,内存使用量受垃圾回收和函数处理期间使用的内存的上限的影响。 可能因呼叫而异,只要gctorture未打开即可。

答案 3 :(得分:0)

您可以使用 PeakRAM 获得处理时间和峰值内存:

library(peakRAM)

peakRAM(smallest.sv())

  Function_Call Elapsed_Time_sec Total_RAM_Used_MiB Peak_RAM_Used_MiB
1 smallest.sv()             3.64                  0              61.1