当迭代一组Rdata文件(每个包含一个HTML代码的字符向量),通过加载,分析(通过XML功能),然后再次从内存中删除,我经历了显着增加
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
Duncan建议试图强制通过.Call(“RS_XML_forceFreeDoc”,html)显式释放已解析的文档.我在示例中添加了一个逻辑开关(在脚本./scripts/memory.R中为do.forcefree),如果设置为TRUE,那么将执行此操作.不幸的是,这使我的R控制台崩溃.如果有人可以在他们的机器上验证这件事情会很棒!实际上,当使用最新版本的XML时,文档应该被自动释放(见上文).事实上它似乎不是一个bug(根据邓肯).
编辑2012-02-14 23:12:00
邓肯将另一个版本的XML(3.92-1)推送到他的Omegahat网站Omegahat website.这应该解决这个问题.然而,我似乎没有运气与我的例子,因为我仍然遇到相同的内存泄漏.
EDIT 2012-02-17 20:39:00>解!
是!邓肯发现并修复了错误!在Windows的唯一脚本中有一点错字,它解释了为什么在Linux,Mac OS等中没有显示错误.请查看最新版本3.92-2.!内存消耗现在与迭代解析和处理XML文件时一样恒定!
特别感谢邓肯寺郎,感谢所有回应这个问题的人!
>>>原始问题的法律部分<<< 示例说明(编辑2012-02-14 15:00:00)
>从我的Github repo下载文件夹’内存’.
>打开脚本./scripts/memory.R并设置a)第6行的工作目录,b)第16行的示例范围,以及c)是否强制释放已解析的文档或不在第22行.请注意,您仍然可以找到旧的脚本;它们被文件名末尾的“LEGACY”标记.
>运行脚本.
>调查最新的文件./memory_\u0026lt;TIMESTAMP\u0026gt;.txt,查看记录内存状态随时间的增加.我已经包含两个由我自己的测试运行产生的文本文件.
关于内存控制的事情
>确保在每次迭代结束时通过rm()重新删除加载的对象.
>在解析XML文件时,我设置了参数addFinalizer = TRUE,删除了所有引用到解析的XML文档的R对象,然后通过free()释放C指针,并删除了包含外部指针的对象.
>在这里和那里添加一个gc().
>尝试遵循Duncan Temple Lang的notes在使用其XML包时进行内存管理的建议(我不得不承认,我并没有完全理解这里所说的内容)
编辑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的初步调查结果
>在几台机器上运行Webscraping方案(参见上面的“系统信息”一节)总是在大约180 – 350次迭代之后破坏了R进程的内存消耗(取决于操作系统和RAM).
>当且仅当您在每次迭代中通过gc()将垃圾回收器设置为显式调用时,运行纯平面rdata方案会产生常量内存消耗;否则你会遇到与webscraping情况相同的行为.
问题
截止2012-02-013 23:44:00
在几台机器上运行示例(./scripts/memory.R)(参见上面的“系统信息”部分),在大约180 – 350次迭代(取决于操作系统和RAM)之后,仍然会破坏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.1和counter.2的值非常感兴趣,在两个调用中应该是1.事实上,在邓肯已经测试过的所有机器上.然而,事实证明,counter.2在我所有的机器上都有值259(见上面的细节),这正是导致我的问题的原因.
老实说,我没有精通你的代码和包的细节,但是我想你可以在该页面找到答案,特别是在“Problems”节,或者直接与邓肯寺交流郎.
更新1.可能有用的一个想法是使用多核和foreach包(即listResults = foreach(ix = 1:N)%dopar%{your processing; return(listElement)})我认为,对于Windows,您将需要doSMP或者可能是doRedis;在Linux下,我使用的是doMC,在任何情况下,通过并行化加载,您将获得更快的吞吐量,我认为您可能从内存使用中获益的原因在于,可能导致不同的内存清理,因为每个产生的进程在完成时都会被杀死,这不能保证工作,但它可以解决内存和速度问题.
请注意,doSMP有其自己的特点(即,您可能还会遇到一些内存问题).还有另外一些关于SO的问题提到了一些问题,但我仍然会给它一个镜头.