当迭代一组Rdata文件(每个包含HTML代码的字符向量)被加载,分析(通过XML功能)然后再次从内存中删除时,我遇到重要< / strong>增加一个 R过程&#39;内存消耗(最终杀死进程)。
看起来好像是
free()
,rm()
和gc()
没有任何影响,所以内存消耗累积,直到没有剩余内存。
感谢包XML的作者和维护者分享的宝贵见解,Duncan Temple Lang(再次:我非常感谢!),问题似乎与外部指针的释放方式密切相关以及如何在XML包中处理垃圾收集。 Duncan发布了一个错误修复版本的软件包(3.92-0),它整合了解析XML和HTML的某些方面,并具有改进的垃圾收集功能,而不再需要通过{显式释放包含外部指针的对象。 {1}}。您可以在Duncan的Omegahat website找到源代码和Windows二进制文件。
不幸的是,新的软件包版本似乎仍然无法解决我在我所放在一起的小小例子中遇到的问题。我遵循了一些建议并简化了示例,使得更容易掌握并找到出现问题的相关函数(检查函数free()
和./lib/exampleRun.R
)。
Duncan建议尝试强制通过.lib/scrape.R
显式释放已解析的文档。我在示例中添加了一个逻辑交换机(脚本.Call("RS_XML_forceFreeDoc", html)
中为do.forcefree
),如果设置为./scripts/memory.R
,则会执行此操作。不幸的是,这让我的R控制台崩溃了。如果有人可以在他们的机器上验证这一点,那就太棒了!实际上,在使用最新版本的XML时,会自动释放doc 文档(参见上文)。事实上它似乎不是一个错误(根据Duncan的说法)。
Duncan将另一个版本的XML(3.92-1)推送到他的Omegahat网站Omegahat website。这应该解决一般问题。但是,我似乎对我的例子运气不好,因为我仍然遇到相同的内存泄漏。
YES!邓肯发现并修复了这个错误!在Windows专用脚本中有点错字,它解释了为什么这个bug在Linux,Mac OS等中没有显示。请查看最新版本3.92-2.!现在,内存消耗与迭代解析和处理XML文件时一样不变!
再次特别感谢Duncan Temple Lang,并感谢回答这个问题的所有人!
TRUE
并设置a)工作目录,b)示例范围 at 第16行以及c)是否在第22行强制释放已解析的文档。请注意,您仍然可以找到旧脚本;他们被标记为#34;通过&#34; LEGACY &#34;在文件名的末尾。./scripts/memory.R
以查看记录的内存状态随时间的增加情况。我已经包含了两个由我自己的测试运行产生的文本文件。./memory_<TIMESTAMP>.txt
再次删除加载的对象。rm()
,在通过addFinalizer=TRUE
释放C指针并删除包含对象之前,删除了所有引用已解析的XML文档的R对象外部指针。free()
。 编辑2012-02-13 23:42:00:
正如我在上面指出的那样,不再需要显式调用gc()
后跟free()
,因此我对这些调用进行了评论。
rm()
设置对垃圾收集器的显式调用时;否则你会遇到与webscraping场景相同的行为。 在几台计算机上运行gc()
中的示例(请参阅&#34;系统信息&#34;上面的部分)在大约180 - 350次迭代后仍会破坏我的R进程的内存消耗(取决于操作系统和内存) )。
内存消耗量仍然明显增加,即使看到这些数字时看起来可能不那么多,但由于这个原因,我的R进程总会在某个时刻死亡。
下面,我发布了几个时间序列,这些时间序列来自在具有2 GB RAM的WinXP 32位盒上运行我的示例:
29.07 33.32 30.55 35.32 30.76 30.94 31.13 31.33 35.44 32.34 33.21 32.18 35.46 35.73 35.76 35.68 35.84 35.6 33.49 33.58 33.71 33.82 33.91 34.04 34.15 34.23 37.85 34.68 34.88 35.05 35.2 35.4 35.52 35.66 35.81 35.91 38.08 36.2
28.54 30.13 32.95 30.33 30.43 30.54 35.81 30.99 32.78 31.37 31.56 35.22 31.99 32.22 32.55 32.66 32.84 35.32 33.59 33.32 33.47 33.58 33.69 33.76 33.87 35.5 35.52 34.24 37.67 34.75 34.92 35.1 37.97 35.43 35.57 35.7 38.12 35.98
./scripts/memory.R
20.1 24.14 24.47 22.03 25.21 25.54 23.15 23.5 26.71 24.6 27.39 24.93 28.06 25.64 28.74 26.36 29.3 27.07 30.01 27.77 28.13 31.13 28.84 31.79 29.54 32.4 30.25 33.07 30.96 33.76 31.66 34.4 32.37 35.1 33.07 35.77 38.23 34.16 34.51 34.87 35.22 35.58 35.93 40.54 40.9 41.33 41.6
[...]
Scraping html page 30 of ~/data/rdata/132.rdata
Scraping html page 31 of ~/data/rdata/132.rdata
error : Memory allocation failed : growing buffer
error : Memory allocation failed : growing buffer
I/O error : write error
Scraping html page 32 of ~/data/rdata/132.rdata
Fehler in htmlTreeParse(file = obj[x.html], useInternalNodes = TRUE, addFinalizer = TRUE):
error in creating parser for (null)
> Synch18832464393836
如果您可以运行以下代码,那么我帮了大忙。 它不会花费超过2分钟的时间。 您需要做的就是
[...]
---------- status: 31.33 % ----------
Scraping html page 1 of 50
Scraping html page 2 of 50
[...]
Scraping html page 36 of 50
Scraping html page 37 of 50
Fehler: 1: Memory allocation failed : growing buffer
2: Memory allocation failed : growing buffer
。seed.Rdata
。代码:
scrape.R
我对setwd("set/path/to/your/wd")
install.packages("XML", repos="http://www.omegahat.org/R")
library(XML)
source("scrape.R")
load("seed.rdata")
html <- htmlParse(obj[1], asText = TRUE)
counter.1 <- .Call("R_getXMLRefCount", html)
print(counter.1)
z <- scrape(html)
gc()
gc()
counter.2 <- .Call("R_getXMLRefCount", html)
print(counter.2)
rm(html)
gc()
gc()
和counter.1
的值特别感兴趣,在两次调用中应为counter.2
。实际上,Duncan已经在所有机器上进行了测试。但是,事实证明1
在我的所有计算机上都有值counter.2
(请参阅上面的详细信息),而这正是造成我问题的原因。
答案 0 :(得分:7)
在XML
软件包的网页上,作者Duncan Temple Lang似乎已经广泛地描述了某些内存管理问题。请参阅此页:"Memory Management in the XML Package"。
老实说,我不熟悉你的代码和软件包的详细信息,但我想你会在那个页面找到答案,特别是在"Problems"一节中,或者与Duncan Temple Lang直接交流。
更新1. 可能工作的想法是使用multicore
和foreach
个包(即listResults = foreach(ix = 1:N) %dopar% {your processing;return(listElement)}
。我认为对于Windows,你会需要doSMP
,或者doRedis
;在Linux下,我使用doMC
。在任何情况下,通过并行加载,您将获得更快的吞吐量。我认为您可能会得到一些内存使用带来的好处是它可能是分叉R,可能会导致不同的内存清理,因为每个生成的进程在完成时都会被杀死。这不能保证工作,但它可以解决内存和速度问题。
请注意:doSMP
有自己的特性(即你可能仍然有一些内存问题)。在SO上还有其他Q&amp; As提到了一些问题,但我还是试一试。
答案 1 :(得分:0)
我在XML包中遇到了类似的问题。 R正在使用的内存量迅速增加,到我的计算机将崩溃的地步。 This answer解决了我的问题,我只设置了addFinalizer = F
。
这是一个最小的可重现示例:
library(tidyverse)
library(XML)
url <- "https://en.wikipedia.org/wiki/Main_Page"
httr::GET(url) %>% base::saveRDS("html.rds")
在运行其他功能之前的内存使用情况:
运行以下命令后的内存使用情况:
for(i in 1:10000){
base::readRDS(file = "html.rds") %>%
XML::htmlParse(., asText=TRUE) %>%
XML::xpathSApply(., path = "//h1", xmlValue, addFinalizer = F)
}
删除addFinalizer = F
(默认)后的内存使用情况:
for(i in 1:10000){
base::readRDS(file = "html.rds") %>%
XML::htmlParse(., asText=TRUE) %>%
XML::xpathSApply(., path = "//h1", xmlValue)
}
答案 2 :(得分:-2)
@Rappster当我第一次检查并确保XML文档存在然后调用C函数来实现内存时,我的R不会崩溃。
for (i in 1:1000) {
pXML<-xmlParse(file)
if(exists("pXML")){
.Call("RS_XML_forceFreeDoc", pXML)
}
}