阅读了 Memory leaks parsing XML in r(包括链接的帖子)和 this在R帮助上的帖子,并且有一段时间已经过去了,我仍然认为这是一个未解决的问题值得关注,因为 XML包被广泛应用于整个R宇宙.

因此,请将此视为跟进帖子和/或参考,并提供有希望的信息,并简要说明问题.

问题

解析XML / HTML文档之后,可以使用XPath进行搜索,需要内部使用C指针(AFAIU).而且看起来至少在MS Windows(我在Windows 8.1,64位上运行)这些引用没有被垃圾回收器正确识别.因此,消耗的存储器未被正确地释放,这导致在某个时刻冻结R过程.

至今中央调查结果

对我来说,XML:free和/或gc在通过xmlParse或htmlParse解析XML / HTML文档时,无法识别所有内存,并随后用xpathApply等进行处理:

所报告的操作系统任务(Rterm.exe)的内存使用量显着加快,而R进程的报告内存“R内”(功能内存大小)从中可以适度增加(相比之下).在下面的实质解析周期之前和之后查看列表元素mem_r,mem_os和比率.

总而言之,扔在推荐的所有东西(free,rm和gc)中,当调用xmlParse等时,内存使用总是会增加.这只是一个多少的问题.所以IMHO还是有一些不能正常工作的东西.

插图

我借鉴了Duncan的Omegahat git repository的分析代码.

一些准备:

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

我们需要的功能:

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,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))

结果

情景1

快速的事实:启用垃圾回收,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

情景2

快速的事实:启用垃圾收集,明确地被调用,XML文档被解析了n次,但没有通过xpathApply进行搜索.

注意OS内存与R内存的比例:

之前:1.315249

之后:1.222143

res <- memoryLeak(clean_up=TRUE,free_doc=TRUE,"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

情景3

快速的事实:启用垃圾回收,明确地调用自由,XML doc被解析n次,并通过xpathApply每次进行搜索.

注意OS内存与R内存的比例:

之前:1.220429

之后:13.15629(!)

res <- memoryLeak(clean_up=TRUE,xpath=TRUE,"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

我也尝试过不同的版本.嗯,我试着尝试;-)

从源头,从omegahat.org

FYI:最新的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

Github上

我没有按照README的github回购建议,因为它指向this directory,只包含一个3.94-0版本的tar.gz(当时我们在CRAN是3.98-1.1).

即使说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)
虽然它还处于起步阶段(只有几个月大!),并且有一些怪癖,哈德利·威克姆(Hadley Wickham)已经编写了一个XML解析库xml2,可以在Github上找到,这个库是 https://github.com/hadley/xml2.它只限于阅读而不是编写XML,但是为了解析XML,我一直在尝试,看起来它会做这个工作,没有xml包的内存泄漏!它提供的功能包括:

> read_xml()来读取一个XML文件
> xml_children()来获取节点的子节点
> xml_text()来获取标签中的文本
> xml_attrs()来获取节点的属性和值的字符向量,可以使用as.list()将其转换为命名列表

请注意,在完成之后,您仍然需要确保您的XML节点对象为rm(),并强制使用gc()进行垃圾收集,但是内存实际上会被释放到O / S(免责声明:只有在Windows 7上测试,但这似乎是最“内存泄漏”的平台).

希望这有助于某人!

在Windows上使用软件包XML时出现内存泄漏的更多相关文章

  1. xcode – Cordova plugin.xml添加“Header Search Paths”条目

    我希望将Cordova插件添加到Xcode项目后,在“HeaderSearchPaths”下添加一个新条目.如何在Cordovaplugin.xml文件中进行配置?

  2. ios – 有关多个连接/提要/视图的XML解析的设计/实现建议

    >我应该在每个视图中都有解析器类/对象或解析XML提要吗?

  3. ios – 为什么重复创建和删除SKShapeNode和SKNode导致内存泄漏?

    使用Xcode附带的spritekit模板,我修改场景如下:该应用程序似乎继续使用更多内存,直到它挂起或崩溃.使用泄漏和分配工具,我发现了以下内容:泄漏:分配:从图像中可以看出,存在大量使用内存的Malloc调用.我不直接调用Malloc–似乎这些调用是由SpriteKit完成的.同样,存在许多内存泄漏,这似乎也是由于SKShapeNode,SKNode或其他SpriteKit对象造成的.我如何解决或解决此内存(泄漏)问题?

  4. ios – Xcode显示内存泄漏,但仪器没有

    当我从Xcode运行我的应用程序时,很明显我有一个内存泄漏:当我提供一个自定义的ViewController时,内存增加,但是当我关闭它时,它不会退回.所以我也检查了使用仪器的分配工具,但这说明了一个不同的故事:可以看出,当我呈现ViewController时,仪器会显示尖峰,但是当内存使用被关闭时,内存使用率将恢复到以前的级别.我已经检查了我的代码至少15次,我个人无法找到任何内存泄漏,因此同意

  5. ios – 内存泄漏与UIWebView和Javascript

    清楚地包含一个Javascript文件到我的HTML是使UIWebView泄漏内存.当我重复使用相同的UIWebView对象时,或者每当我有内容实例化一个新的漏洞时,会出现泄漏的事实,导致我认为必须有一些JavaScript文件被loadHTMLString处理,导致泄漏.有人知道如何解决这个问题吗?

  6. iOS的相当于Android的colors.xml的是什么?

    如果没有,组织整个应用程序使用的颜色的最佳方法是什么?

  7. iOS中的XML转换为JSON

    我需要将XML响应转换为JSON.我的XML响应:我正在使用本网站的XMLReader支持文件:XMLReader我正在使用此代码将XML转换为JSON我收到了JSON响应:我需要这样的回应:我在线转换时得到这个回应.如何获得这样的回应提前致谢.解决方法此代码不会将任何内容转换为JSON.它给你一个NSDictionary.您需要从字典中实际创建JSON数据.尝试这个大小.

  8. ios – Info.plist格式不正确

    解决方法plist文件是严格指定格式的XML文档;XML和PropertyList结构都有非常严格的规则.如果您尝试手动编辑info.plist(即文本),您可以轻松搞砸事情,方法是打开Asas>源代码:您不太可能正确使用此格式.因此,您应该始终使用OpenAs>编辑info.plist.物业清单:这允许属性列表编辑器为您生成XML,并且不太可能在生成的XML结构中出错.当然,我想你仍然可能搞砸某些东西的价值……

  9. ios – 在没有XML的情况下更新sqlite数据库

    我的应用程序需要来自sqlite数据库的数据.它将附带此数据库的一个版本,但我需要定期更新它(很可能每月一次).通常情况下,我一直在通过我设置的一堆网络服务将我的应用程序的其他部分的更新作为XML发送,但我现在正在处理的这个特定数据库非常大(大约20-30MB),而且我当我尝试以这种方式发送时出现超时错误.我尝试将数据库放在我的公司服务器上,然后将其下载到NSData对象中.然后我将该数据对象保存

  10. ios – SBJson – 有内存泄漏?

    我刚刚克隆了SBJson框架的git存储库,并将源代码导入到我的应用程序中.跑了一个静态内存探查器,并从我看到的结果有点害怕.看图这怎么可能?我怀疑这个知名图书馆的开发者没有看到这个?事实上,如果运行内存配置文件,它会显示此库中的内存泄漏.有任何想法吗?

随机推荐

  1. static – 在页面之间共享数据的最佳实践

    我想知道在UWP的页面之间发送像’selectedItem’等变量的最佳做法是什么?创建一个每个页面都知道的静态全局变量类是一个好主意吗?

  2. .net – 为Windows窗体控件提供百分比宽度/高度

    WindowsForm开发的新手,但在Web开发方面经验丰富.有没有办法为Windows窗体控件指定百分比宽度/高度,以便在用户调整窗口大小时扩展/缩小?当窗口调整大小时,可以编写代码来改变控件的宽度/高度,但我希望有更好的方法,比如在HTML/CSS中.在那儿?

  3. 使用Windows Azure查询表存储数据

    我需要使用特定帐户吗?>将应用程序部署到Azure服务后,如何查询数据?GoogleAppEngine有一个数据查看器/查询工具,Azure有类似的东西吗?>您可以看到的sqlExpressintance仅在开发结构中,并且一旦您表示没有等效,所以请小心使用它.>您可以尝试使用Linqpad查询表格.看看JamieThomson的thispost.

  4. windows – SetupDiGetClassDevs是否与文档中的设备实例ID一起使用?

    有没有更好的方法可以使用DBT_DEVICEARRIVAL事件中的数据获取设备的更多信息?您似乎必须指定DIGCF_ALLCLASSES标志以查找与给定设备实例ID匹配的所有类,或者指定ClassGuid并使用DIGCF_DEFAULT标志.这对我有用:带输出:

  5. Windows Live ID是OpenID提供商吗?

    不,WindowsLiveID不是OpenID提供商.他们使用专有协议.自从他们的“测试版”期结束以来,他们从未宣布计划继续它.

  6. 如果我在代码中进行了更改,是否需要重新安装Windows服务?

    我写了一个Windows服务并安装它.现在我对代码进行了一些更改并重新构建了解决方案.我还应该重新安装服务吗?不,只需停止它,替换文件,然后重新启动它.

  7. 带有双引号的字符串回显使用Windows批处理输出文件

    我正在尝试使用Windows批处理文件重写配置文件.我循环遍历文件的行并查找我想要用指定的新行替换的行.我有一个’函数’将行写入文件问题是%Text%是一个嵌入双引号的字符串.然后失败了.可能还有其他角色也会导致失败.如何才能使用配置文件中的所有文本?尝试将所有“在文本中替换为^”.^是转义字符,因此“将被视为常规字符你可以尝试以下方法:其他可能导致错误的字符是:

  8. .net – 将控制台应用程序转换为服务?

    我正在寻找不同的优势/劣势,将我们长期使用的控制台应用程序转换为Windows服务.我们为ActiveMQ使用了一个叫做java服务包装器的东西,我相信人们告诉我你可以用它包装任何东西.这并不是说你应该用它包装任何东西;我们遇到了这个问题.控制台应用程序是一个.NET控制台应用程序,默认情况下会将大量信息记录到控制台,尽管这是可配置的.任何推荐?我们应该在VisualStudio中将其重建为服务吗?我使用“-install”/“-uninstall”开关执行此操作.例如,seehere.

  9. windows – 捕获外部程序的STDOUT和STDERR *同时*它正在执行(Ruby)

    哦,我在Windows上:-(实际上,它比我想象的要简单,这看起来很完美:…是的,它适用于Windows!

  10. windows – 当我试图批量打印变量时,为什么我得到“Echo is on”

    我想要执行一个简单的批处理文件脚本:当我在XP中运行时,它给了我预期的输出,但是当我在Vista或Windows7中运行它时,我在尝试打印值时得到“EchoisOn”.以下是程序的输出:摆脱集合表达式中的空格.等号(=)的两侧可以并且应该没有空格BTW:我通常在@echo关闭的情况下启动所有批处理文件,并以@echo结束它们,所以我可以避免将代码与批处理文件的输出混合.它只是使您的批处理文件输出更好,更清洁.

返回
顶部