由于XML,R不会停止抓取内存/RAM

由于XML,R不会停止抓取内存/RAM,xml,r,loops,Xml,R,Loops,我有一个如下所示的双循环问题是R(2.15.2)正在使用越来越多的内存,我不明白为什么 虽然我知道这必须发生在内部循环中,因为我在那里做的是rbind(),但我不明白为什么在外部循环的新循环开始时,R会一直抓取内存,并且实际上对象('xmlCatcher')被重用: # !!!BEWARE this example creates a lot of files (n=1000)!!!! require(XML) chunk <- function(x, chunksize){

我有一个如下所示的双循环问题是R(2.15.2)正在使用越来越多的内存,我不明白为什么

虽然我知道这必须发生在内部循环中,因为我在那里做的是
rbind()
,但我不明白为什么在外部循环的新循环开始时,R会一直抓取内存,并且实际上对象('xmlCatcher')被重用:

# !!!BEWARE this example creates a lot of files (n=1000)!!!!

require(XML)

chunk <- function(x, chunksize){
        # source: http://stackoverflow.com/a/3321659/1144966
        x2 <- seq_along(x)
        split(x, ceiling(x2/chunksize))
    }

chunky <- chunk(paste("test",1:1000,".xml",sep=""),100)

for(i in 1:1000){
writeLines(c(paste('<?xml version="1.0"?>\n <note>\n    <to>Tove</to>\n    <nr>',i,'</nr>\n    <from>Jani</from>\n    <heading>Reminder</heading>\n    ',sep=""), paste(rep('<body>Do not forget me this weekend!</body>\n',sample(1:10, 1)),sep="" ) , ' </note>')
,paste("test",i,".xml",sep=""))
}

for(k in 1:length(chunky)){
gc()
print(chunky[[k]])
xmlCatcher <- NULL

for(i in 1:length(chunky[[k]])){
    filename    <- chunky[[k]][i]
    xml         <- xmlTreeParse(filename)
    xml         <- xmlRoot(xml)
    result      <- sapply(getNodeSet(xml,"//body"), xmlValue)
    id          <- sapply(getNodeSet(xml,"//nr"), xmlValue)
    dummy       <- cbind(id,result)
    xmlCatcher  <- rbind(xmlCatcher,dummy)
    }
save(xmlCatcher,file=paste("xmlCatcher",k,".RData"))
}
#!!!注意这个例子创建了很多文件(n=1000)!!!!
需要(XML)
chunk的第二个话题是把rbind
rbind
作为一种常见的贪吃手段

您可以避免在循环中使用
rbind

my.list <- vector('list', chunk[k])
for(i in 1:chunk[k]) {
   dummy <- dummy + 1
   my.list[[i]] <- data.frame(dummy)
}
DummyCatcher  <- do.call('rbind', my.list)

my.list您对重用内存的理解是错误的

当您创建新的DummyCatcher时,旧的DummyCatcher将不再被引用,然后成为垃圾收集的候选对象,这将在某个时候发生

您不是在重用内存,而是在创建一个新对象并放弃旧对象

垃圾回收将释放内存


此外,我建议您查看Rprofmem以分析您的内存使用情况

这是一个愚蠢的XML包


米兰·布切特·瓦拉特(Milan Bouchet Valat)给出了这个问题的答案,他建议我尝试使用
useInternalNodes=TRUE
-选项作为
xmlTreeParse
。这停止了RAM抓取,尽管也有可能手动处理内存释放。如需进一步阅读,请参阅:。

通常,在循环内部使用
rbind
不是好的做法。我建议创建一个具有所需长度的对象,并覆盖其值(通过索引)。行
DummyCatcher=rbind(DummyCatcher,dummy)
表示在每次迭代中增加
DummyCatcher
,因此内存会增加。@SvenHohenstein我会按照建议做,但“真实”循环的结果可能在长度上有所不同,因此我事先不知道结果会有多长。让对象在循环中增长不是一个好主意,因为每次运行
rbind
都会创建一个新对象。当然,之后可以释放分配给旧对象的内存。但另一个问题是它需要相当长的时间。作为旁注,您应该避免使用诸如
for(k in 1:length(chunk))
之类的语句。如果
块的长度
为零,则变为
1:0
,即
c(1,0)
,尽管其预期为
NULL
。最好使用
来表示(块中的k)
。加上1只用于引用Burns的书。我最喜欢的参考资料之一。-1如果有足够的声誉:它根本没有帮助,我尝试过,内存使用量也在以同样的方式增长:my.list垃圾收集“gc()”实际上根本没有帮助。我把它放在更新的示例中,没有任何变化。关于Rprofmem的想法,我不明白如何利用它。它是有效的,但这些数字是一个奇迹。你创建了越来越大的对象,为什么你期望使用的内存不会增长?事实上,我创建了增长的对象,然后我再次告诉它们为
NULL
,让它们再次增长。因此,我希望内存使用量会一直增长到第一个内部循环结束,从那时起应该保持几乎不变,因为1)R在怀疑需要内存时不会提供空闲内存,因此我希望R在抓取RAM后保留RAM,除非其他地方需要它;2) 设置为
NULL
的对象填充的数据量大致相同,因此我希望R不会进一步抓取RAM。请尝试在
xmlCatcher之后调用
gc()