r - 迭代解析XML文件时出现严重的内存泄漏

标签 r xml memory-leaks

语境

遍历一组已加载,分析(通过XML功能)然后再次从内存中删除的Rdata文件(每个文件都包含HTML代码的字符向量)时,我发现
R进程的内存消耗(最终杀死进程)。

好像


通过free()释放对象,
通过rm()删除它们,然后
正在运行gc()


不会有任何影响,因此直到不再有可用的内存为止,内存消耗才会累积。

编辑2012-02-13 23:30:00

得益于软件包XML的作者和维护者Duncan Temple Lang的宝贵见解(再次,我非常感谢!),该问题似乎与释放外部指针的方式以及如何进行垃圾回收紧密相关。在XML包中处理。 Duncan发布了该程序包的一个错误修复版本(3.92-0),该版本合并了解析XML和HTML的某些方面,并具有改进的垃圾回收功能,不再需要通过free()显式释放包含外部指针的对象。您可以在Duncan的Omegahat website中找到源代码和Windows二进制文件。



编辑2012-02-13 23:34:00

不幸的是,新的软件包版本似乎仍无法解决我整理的一个小示例中遇到的问题。我遵循了一些建议,并简化了示例,使其更易于掌握和查找出现问题的相关功能(检查功能./lib/exampleRun.R.lib/scrape.R)。



编辑2012-02-14 15:00:00

邓肯建议尝试通过.Call("RS_XML_forceFreeDoc", html)显式释放解析的文档。我在示例中包含了一个逻辑开关(脚本do.forcefree中的./scripts/memory.R),如果将其设置为TRUE,它将执行此操作。不幸的是,这使我的R控制台崩溃了。如果有人可以在他们的计算机上验证这一点,那就太好了!实际上,使用最新版本的XML(请参见上文)时,应自动释放文档。事实并非如此(根据Duncan的说法)。



编辑2012-02-14 23:12:00

Duncan将另一个XML(3.92-1)版本推到了他的Omegahat网站Omegahat website。总体而言,这应该可以解决该问题。但是,我的示例似乎不走运,因为我仍然遇到相同的内存泄漏。



EDIT 2012-02-17 20:39:00>解决方案!

是! Duncan发现并修复了该错误!这是纯Windows脚本中的一个小错字,它解释了为什么该错误未在Linux,Mac OS等操作系统中显示。请查看最新版本3.92-2.!现在,内存消耗与迭代解析和处理XML文件时一样恒定!

再次特别感谢Duncan Temple Lang,并感谢其他回答此问题的人!



>>>原始问题的旧部分<<<

示例说明(于2012-02-14 15:00:00编辑)


从我的Github repo下载文件夹“ memory”。
打开脚本./scripts/memory.R并在第6行设置a)您的工作目录,b)在第16行也设置示例范围c)是否在第22行是否强制释放已解析的文档。请注意,您仍然可以找到旧的脚本;它们在文件名的末尾用“ LEGACY”“标记”。
运行脚本。
研究最新文件./memory_<TIMESTAMP>.txt以查看记录的内存状态随时间的增加。我包括了两个文本文件,这些文件是我自己的测试运行产生的。


我在内存控制方面所做的事情


确保在每次迭代结束时通过rm()再次删除加载的对象。
解析XML文件时,我设置了参数addFinalizer=TRUE,在通过free()释放C指针并删除包含外部指针的对象之前,删除了对已解析的XML文档有引用的所有R对象。
在此添加gc()
在使用XML包时尝试遵循Duncan Temple Lang的notes中有关内存管理的建议(我必须承认,尽管我没有完全理解那里的内容)


编辑2012-02-13 23:42:00:
正如我在上面指出的那样,不再需要先显式调用free(),然后再调用rm(),因此我将这些调用注释掉了。

系统信息


Windows XP 32位,4 GB RAM
Windows 7 32位,2 GB RAM
Windows 7 64位,4 GB RAM
R 2.14.1
XML 3.9-4
XML 3.92-0(在http://www.omegahat.org/RSXML/中找到)


截至2012-02-09 01:00:00的初步发现


在大约180-350次迭代(取决于OS和RAM)之后,在多台机器上运行webscraping方案(请参阅上面的“系统信息”一节)总是会破坏我的R进程的内存消耗。
当且仅当在每次迭代中通过gc()设置对垃圾收集器的显式调用时,运行普通rdata方案才会产生恒定的内存消耗。否则,您会遇到与网络抓取场景相同的行为。


问题


知道导致内存增加的原因是什么?
任何想法如何解决这个问题?


截至2012-02-013 23:44:00的发现

在大约180-350次迭代(取决于OS和RAM)之后,在多台计算机上的./scripts/memory.R中运行示例(请参见上面的“系统信息”一节)仍然会破坏我的R进程的内存消耗。

内存消耗仍然有明显的增加,尽管仅看数字似乎并没有那么多,但由于这个原因,我的R进程总是在某个时候终止。

下面,我发布了一些时间序列,这些时间序列是在具有2 GB RAM的WinXP 32位盒上运行示例后得出的:

TS_1(XML 3.9-4,2012-02-09)

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

TS_2(XML 3.9-4,2012-02-09)

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

与TS_2相关的错误消息

[...]
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


TS_3(XML 3.92-0,2012-02-13)

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

与TS_3相关的错误消息

[...]
---------- 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




编辑2012-02-17:请帮助我验证计数器值

如果可以运行以下代码,您将对我有很大帮助。
您的时间不会超过2分钟。
您需要做的就是


下载Rdata file并将其另存为seed.Rdata
下载包含我的scraping function的脚本,并将其另存为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.1counter.2的值特别感兴趣,这两个调用中的值均应为1。实际上,邓肯已经在所有机器上对其进行了测试。但是,事实证明counter.2在我所有的机器上都具有值259(请参见上面的详细信息),这正是导致我的问题的原因。

最佳答案

XML包的网页上,作者Duncan Temple Lang似乎已经相当广泛地描述了某些内存管理问题。参见本页:"Memory Management in the XML Package"

老实说,我不精通代码和程序包的详细信息,但我想您可以在该页面(特别是"Problems"部分)找到答案,或者直接与邓肯神庙郎。



更新1.更新的一种可行方法是使用multicoreforeach软件包(即listResults = foreach(ix = 1:N) %dopar% {your processing;return(listElement)}。我认为对于Windows,您将需要doSMPdoRedis;在Linux下,我使用doMC。无论如何,通过并行化加载,您将获得更快的吞吐量,我认为您可以从内存使用中获得一些好处的原因是,叉R可能导致不同的内存清理,因为每次产生的进程在完成时会被杀死,虽然不能保证正常工作,但可以解决内存和速度问题。

不过请注意:doSMP有其自身的特质(即,您可能仍会遇到一些内存问题)。关于SO的其他问答也提到了一些问题,但我还是会尝试一下。

关于r - 迭代解析XML文件时出现严重的内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9220849/

相关文章:

r - 即使小数点后的所有内容都是零,也能找到小数点

android - Activity xml 中的 Fragment 中的 findViewById 属性不起作用

regex - XML 中无效字符的正则表达式

c++ - Visual Studio 中的内存泄漏

r - 选择数据 - 第一个条目 + 设置时间段(1 年)R

r - 使用 R 数据表计算累计日期的罢工率

r - 排除导入中的函数 - 命名空间

java - 是否有一个 SaxParser 可以读取 json 并触发事件,所以它看起来像 xml

ios - skmaps 通过更新 SKAnnotation 来解决巨大的内存泄漏

Android Media player 保留应用程序实例并导致内存泄漏