由于XML,R不会停止抓取内存/RAM
我有一个如下所示的双循环问题是R(2.15.2)正在使用越来越多的内存,我不明白为什么 虽然我知道这必须发生在内部循环中,因为我在那里做的是由于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){
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的第二个话题是把rbindrbind
作为一种常见的贪吃手段
您可以避免在循环中使用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()