Rap*_*ter 11 xml windows parsing memory-leaks r
阅读内存泄漏解析r中的XML(包括链接的帖子)和R帮助上的这篇文章,并且鉴于已经过了一段时间,我仍然认为这是一个值得关注的未解决的问题,因为该XML软件包在整个R宇宙中被广泛使用.
因此,请将此视为后续帖子和/或参考,并提供有希望的信息性但简洁的问题说明.
以后可以使用XPath搜索XML/HTML文档的方式需要内部使用C指针(AFAIU).而且似乎至少在MS Windows上(我在Windows 8.1,64位上运行)这些引用都没有被垃圾收集器正确识别.因此,消耗的内存未被正确释放,这导致在某个时刻冻结R进程.
对我而言,似乎XML:free和/或gc确实/ /或不识别通过或随后使用等处理XML/HTML文档时涉及的所有内存:xmlParsehtmlParsexpathApply
报告的OS任务(Rterm.exe)的内存使用量显着增加,而R进程的报告内存"从R内看"(函数memory.size)适度增加(相比之下).请参阅列表元素mem_r,mem_os以及ratio下面的实质解析周期之前和之后.
所有的一切,并已建议一切抛(free,rm和gc),内存使用率仍然一直增加时xmlParse等被调用.这只是一个多少的问题.所以恕我直言必须仍然有一些不正常的东西.
我从Duncan的Omegahat git存储库中借用了性能分析代码.
一些准备:
Sys.setenv("LANGUAGE"="en")
require("compiler")
require("XML")
> sessionInfo()
R version 3.1.0 (2014-04-10)
Platform: x86_64-w64-mingw32/x64 (64-bit)
locale:
[1] LC_COLLATE=German_Germany.1252 LC_CTYPE=German_Germany.1252
[3] LC_MONETARY=German_Germany.1252 LC_NUMERIC=C
[5] LC_TIME=German_Germany.1252
attached base packages:
[1] compiler stats graphics grDevices utils datasets methods
[8] base
other attached packages:
[1] XML_3.98-1.1
Run Code Online (Sandbox Code Playgroud)
我们需要的功能:
getTaskMemoryByPid <- cmpfun(function(
pid=Sys.getpid()
) {
cmd <- sprintf("tasklist /FI \"pid eq %s\" /FO csv", pid)
mem <- read.csv(text=shell(cmd, intern = TRUE), stringsAsFactors=FALSE)[,5]
mem <- as.numeric(gsub("\\.|\\s|K", "", mem))/1000
mem
}, options=list(suppressAll=TRUE))
memoryLeak <- cmpfun(function(
x=system.file("exampleData", "mtcars.xml", package="XML"),
n=10000,
use_text=FALSE,
xpath=FALSE,
free_doc=FALSE,
clean_up=FALSE,
detailed=FALSE
) {
if(use_text) {
x <- readLines(x)
}
## Before //
mem_os <- getTaskMemoryByPid()
mem_r <- memory.size()
prof_1 <- memory.profile()
mem_before <- list(mem_r=mem_r,
mem_os=mem_os, ratio=mem_os/mem_r)
## Per run //
mem_perrun <- lapply(1:n, function(ii) {
doc <- xmlParse(x, asText=use_text)
if (xpath) {
res <- xpathApply(doc=doc, path="/blah", fun=xmlValue)
rm(res)
}
if (free_doc) {
free(doc)
}
rm(doc)
out <- NULL
if (detailed) {
out <- list(
profile=memory.profile(),
size=memory.size()
)
}
out
})
has_perrun <- any(sapply(mem_perrun, length) > 0)
if (!has_perrun) {
mem_perrun <- NULL
}
## Garbage collect //
mem_gc <- NULL
if(clean_up) {
gc()
tmp <- gc()
mem_gc <- list(gc_mb=tmp["Ncells", "(Mb)"])
}
## After //
mem_os <- getTaskMemoryByPid()
mem_r <- memory.size()
prof_2 <- memory.profile()
mem_after <- list(mem_r=mem_r,
mem_os=mem_os, ratio=mem_os/mem_r)
list(
before=mem_before,
perrun=mem_perrun,
gc=mem_gc,
after=mem_after,
comparison_r=data.frame(
before=prof_1,
after=prof_2,
increase=round((prof_2/prof_1)-1, 4)
),
increase_r=(mem_after$mem_r/mem_before$mem_r)-1,
increase_os=(mem_after$mem_os/mem_before$mem_os)-1
)
}, options=list(suppressAll=TRUE))
Run Code Online (Sandbox Code Playgroud)
快速事实:启用垃圾收集,XML文档解析n时间但不通过搜索xpathApply
注意OS内存与R内存的比率:
之前: 1.364832
后: 1.322702
res <- memoryLeak(clean_up=TRUE, n=50000)
save(res, file=file.path(tempdir(), "memory-profile-1.rdata"))
> res
$before
$before$mem_r
[1] 37.42
$before$mem_os
[1] 51.072
$before$ratio
[1] 1.364832
$perrun
NULL
$gc
$gc$gc_mb
[1] 45
$after
$after$mem_r
[1] 63.21
$after$mem_os
[1] 83.608
$after$ratio
[1] 1.322702
$comparison_r
before after increase
NULL 1 1 0.0000
symbol 7387 7392 0.0007
pairlist 190383 390633 1.0518
closure 5077 55085 9.8499
environment 1032 51032 48.4496
promise 5226 105226 19.1351
language 54675 54791 0.0021
special 44 44 0.0000
builtin 648 648 0.0000
char 8746 8763 0.0019
logical 9081 9084 0.0003
integer 22804 22807 0.0001
double 2773 2783 0.0036
complex 1 1 0.0000
character 44522 94569 1.1241
... 0 0 NaN
any 0 0 NaN
list 19946 19951 0.0003
expression 1 1 0.0000
bytecode 16049 16050 0.0001
externalptr 1487 1487 0.0000
weakref 391 391 0.0000
raw 392 392 0.0000
S4 1392 1392 0.0000
$increase_r
[1] 0.6892036
$increase_os
[1] 0.6370614
Run Code Online (Sandbox Code Playgroud)
快速事实:启用垃圾收集,free显式调用,XML文档解析n时间但不通过搜索xpathApply.
注意OS内存与R内存的比率:
之前: 1.315249
后: 1.222143
res <- memoryLeak(clean_up=TRUE, free_doc=TRUE, n=50000)
save(res, file=file.path(tempdir(), "memory-profile-2.rdata"))
> res
$before
$before$mem_r
[1] 63.48
$before$mem_os
[1] 83.492
$before$ratio
[1] 1.315249
$perrun
NULL
$gc
$gc$gc_mb
[1] 69.3
$after
$after$mem_r
[1] 95.92
$after$mem_os
[1] 117.228
$after$ratio
[1] 1.222143
$comparison_r
before after increase
NULL 1 1 0.0000
symbol 7454 7454 0.0000
pairlist 392455 592466 0.5096
closure 55104 105104 0.9074
environment 51032 101032 0.9798
promise 105226 205226 0.9503
language 55592 55592 0.0000
special 44 44 0.0000
builtin 648 648 0.0000
char 8847 8848 0.0001
logical 9141 9141 0.0000
integer 23109 23111 0.0001
double 2802 2807 0.0018
complex 1 1 0.0000
character 94775 144781 0.5276
... 0 0 NaN
any 0 0 NaN
list 20174 20177 0.0001
expression 1 1 0.0000
bytecode 16265 16265 0.0000
externalptr 1488 1487 -0.0007
weakref 392 391 -0.0026
raw 393 392 -0.0025
S4 1392 1392 0.0000
$increase_r
[1] 0.5110271
$increase_os
[1] 0.4040627
Run Code Online (Sandbox Code Playgroud)
快速的事实:垃圾收集启用,free被显式调用,XML文档进行解析n时间和搜查通过xpathApply各一次.
注意OS内存与R内存的比率:
之前: 1.220429
之后:(13.15629!)
res <- memoryLeak(clean_up=TRUE, free_doc=TRUE, xpath=TRUE, n=50000)
save(res, file=file.path(tempdir(), "memory-profile-3.rdata"))
res
$before
$before$mem_r
[1] 95.94
$before$mem_os
[1] 117.088
$before$ratio
[1] 1.220429
$perrun
NULL
$gc
$gc$gc_mb
[1] 93.4
$after
$after$mem_r
[1] 124.64
$after$mem_os
[1] 1639.8
$after$ratio
[1] 13.15629
$comparison_r
before after increase
NULL 1 1 0.0000
symbol 7454 7460 0.0008
pairlist 592458 793042 0.3386
closure 105104 155110 0.4758
environment 101032 151032 0.4949
promise 205226 305226 0.4873
language 55592 55882 0.0052
special 44 44 0.0000
builtin 648 648 0.0000
char 8847 8867 0.0023
logical 9142 9162 0.0022
integer 23109 23112 0.0001
double 2802 2832 0.0107
complex 1 1 0.0000
character 144775 194819 0.3457
... 0 0 NaN
any 0 0 NaN
list 20174 20177 0.0001
expression 1 1 0.0000
bytecode 16265 16265 0.0000
externalptr 1488 1487 -0.0007
weakref 392 391 -0.0026
raw 393 392 -0.0025
S4 1392 1392 0.0000
$increase_r
[1] 0.2991453
$increase_os
[1] 13.00485
Run Code Online (Sandbox Code Playgroud)
我也试过不同的版本.好吧,我试着尝试;-)
仅供参考:最新的Rtools 3.1已安装并包含在Windows中PATH(例如,安装stringr表单源代码工作正常).
> install.packages("XML", repos="http://www.omegahat.org/R", type="source")
trying URL 'http://www.omegahat.org/R/src/contrib/XML_3.98-1.tar.gz'
Content type 'application/x-gzip' length 1543387 bytes (1.5 Mb)
opened URL
downloaded 1.5 Mb
* installing *source* package 'XML' ...
Please define LIB_XML (and LIB_ZLIB, LIB_ICONV)
Warning: running command 'sh ./configure.win' had status 1
ERROR: configuration failed for package 'XML'
* removing 'R:/home/apps/lsqmapps/apps/r/R-3.1.0/library/XML'
* restoring previous 'R:/home/apps/lsqmapps/apps/r/R-3.1.0/library/XML'
The downloaded source packages are in
'C:\Users\rappster_admin\AppData\Local\Temp\RtmpQFZ2Ck\downloaded_packages'
Warning messages:
1: running command '"R:/home/apps/lsqmapps/apps/r/R-3.1.0/bin/x64/R" CMD INSTALL -l "R:\home\apps\lsqmapps\apps\r\R-3.1.0\library" C:\Users\RAPPST~1\AppData\Local\Temp\RtmpQFZ2Ck/downloaded_packages/XML_3.98-1.tar.gz' had status 1
2: In install.packages("XML", repos = "http://www.omegahat.org/R", :
installation of package 'XML' had non-zero exit status
Run Code Online (Sandbox Code Playgroud)
我没有按照github repo上的README中的建议,因为它指向的目录只包含一个tar.gz版本3.94-0(当我们处于3.98-1.1CRAN时).
尽管有人说gihub repo不是标准的R包结构,但无论如何我试过了install_github- 并且失败了;-)
require("devtools")
> install_github(repo="XML", username="omegahat")
Installing github repo XML/master from omegahat
Downloading master.zip from https://github.com/omegahat/XML/archive/master.zip
Installing package from C:\Users\RAPPST~1\AppData\Local\Temp\RtmpQFZ2Ck/master.zip
Installing XML
"R:/home/apps/lsqmapps/apps/r/R-3.1.0/bin/x64/R" --vanilla CMD INSTALL \
"C:\Users\rappster_admin\AppData\Local\Temp\RtmpQFZ2Ck\devtools15c82d7c2b4c\XML-master" \
--library="R:/home/apps/lsqmapps/apps/r/R-3.1.0/library" --with-keep.source \
--install-tests
* installing *source* package 'XML' ...
Please define LIB_XML (and LIB_ZLIB, LIB_ICONV)
Warning: running command 'sh ./configure.win' had status 1
ERROR: configuration failed for package 'XML'
* removing 'R:/home/apps/lsqmapps/apps/r/R-3.1.0/library/XML'
* restoring previous 'R:/home/apps/lsqmapps/apps/r/R-3.1.0/library/XML'
Error: Command failed (1)
Run Code Online (Sandbox Code Playgroud)
虽然它仍处于起步阶段(只有几个月的历史!),并且有一些怪癖,但 Hadley Wickham 已经编写了一个用于 XML 解析的库,xml2可以在 Github 上找到:https://github.com/hadley /xml2。它仅限于读取而不是写入 XML,但是对于解析 XML,我一直在尝试,看起来它可以完成这项工作,而不会出现 xml 包的内存泄漏!它提供的功能包括:
read_xml()读取 XML 文件xml_children()获取节点的子节点xml_text()获取标签内的文本xml_attrs()获取节点的属性和值的字符向量,可以将其转换为命名列表as.list()请注意,您仍然需要确保rm()在使用完 XML 节点对象后,使用它们强制进行垃圾回收gc(),但内存实际上会释放到操作系统(免责声明:仅在 Windows 7 上进行了测试,但无论如何,这似乎是最“内存泄漏”的平台)。
希望这对某人有帮助!
| 归档时间: |
|
| 查看次数: |
736 次 |
| 最近记录: |