Серьезная утечка памяти при итеративном разборе файлов XML
При переборе набора файлов Rdata (каждый из которых содержит вектор символов HTML-кода), которые загружаются, анализируются (с помощьюXML функциональность), а затем снова удалены из памяти, я испытываюсущественный увеличение потребления памяти процессом R (убивая процесс в конечном счете).
Это просто кажется
освобождение объектов черезfree()
,удаляя их черезrm()
а такжеБегgc()
не имеют никаких эффектов, поэтому потребление памяти накапливается до тех пор, пока не останется больше памяти.
РЕДАКТИРОВАТЬ 2012-02-13 23:30:00Благодаря ценной информации, которой поделились автор и разработчик пакетаXMLДункан Темпл Лэнг (снова: я действительно очень ценю это!), Проблема, кажется, тесно связана с тем, как освобождаются внешние указатели и как сборка мусора обрабатывается в пакете XML. Дункан выпустил исправленную версию пакета (3.92-0), в которой объединены некоторые аспекты синтаксического анализа XML и HTML и улучшена сборка мусора, когда больше нет необходимости явно освобождать объект, содержащий внешний указатель, черезfree()
, Вы найдете исходный код и бинарный файл Windows у ДунканаВеб-сайт омегахата.
К сожалению, новая версия пакета все еще не решает проблемы, с которыми я сталкиваюсь в небольшом небольшом примере, который я собрал. Я последовал некоторому предложению и немного упростил пример, чтобы было легче понять и найти соответствующие функции там, где кажется, что что-то идет не так (проверьте функции./lib/exampleRun.R
а также.lib/scrape.R
).
Дункан предложил попытаться принудительно освободить разобранный документ через.Call("RS_XML_forceFreeDoc", html)
, Я включил логический переключатель в примере (do.forcefree
в сценарии./scripts/memory.R
) что, если установленоTRUE
, сделаю именно это. К сожалению, это привело к краху моей консоли R. Было бы здорово, если бы кто-то мог проверить это на своей машине! На самом деле, докдолжен быть освобожден автоматически при использовании последней версии XML (см. выше). Факт, что это не кажется ошибкой (согласно Дункану).
Дункан выдвинул еще одну версию XML (3.92-1) на свой веб-сайт OmegahatВеб-сайт омегахата, Это должно решить проблему в целом. Однако мне, кажется, не повезло с моим примером, поскольку я все еще испытываю ту же утечку памяти.
РЕДАКТИРОВАТЬ 17-02-2012, 20:39> РЕШЕНИЕ!ДА! Дункан нашел и исправил ошибку! Это была небольшая опечатка в сценарии только для Windows, которая объясняла, почему ошибка не отображалась в Linux, Mac OS и т. Д. Проверьте последнюю версию3.92-2.! Потребление памяти стало таким же постоянным, как и при итеративном анализе и обработке файлов XML!
Отдельное спасибо Duncan Temple Lang и всем остальным, кто ответил на этот вопрос!
>>> ЧАСТИ УЧАСТИЯ ОРИГИНАЛЬНОГО ВОПРОСА <<<Пример инструкции (отредактировано 2012-02-14 15:00:00)Скачать папку'Память' от моегоGithub репо.Откройте скрипт./scripts/memory.R
и установите а) вашрабочий каталог встрока 6б)пример объема встрока 16 а также c) принудительно ли освобождать проанализированный документ или нет встрока 22, Обратите внимание, что вы все еще можете найти старые скрипты; они помеченыLEGACY"в конце имени файла.Запустите скрипт.Исследуйте последний файл./memory_<TIMESTAMP>.txt
чтобы увидеть увеличение зарегистрированных состояний памяти с течением времени. Я включил два текстовых файла, которые были получены в результате моих собственных тестов.Вещи, которые я сделал в отношении контроля памятиубедившись, что загруженный объект снова удаляется с помощьюrm()
в конце каждой итерации.При разборе файлов XML я установил аргументaddFinalizer=TRUE
, удалил все объекты R, которые имеют ссылку на проанализированный документ XML, прежде чем освобождать указатель C черезfree()
и удаление объекта, содержащего внешний указатель.добавивgc()
тут и там.пытаясь следовать советам в Дункан Темпл ЛэнгсПримечания на управление памятью при использовании его пакета XML (я должен признать, что я не полностью понял, что там сказано)РЕДАКТИРОВАТЬ 13-02-2012 23:42:00: Как я уже говорил выше, явные призывы кfree()
с последующимrm()
не должно быть больше необходимости, поэтому я прокомментировал эти призывы.
gc()
в каждой итерации; иначе вы испытываете то же поведение, что и в сценарии веб-скрепинга.ВопросовЕсть идеи, что вызывает увеличение памяти?Есть идеи, как обойти это?Результаты по состоянию на 2012-02-013 23:44:00Запуск примера в./scripts/memory.R
на нескольких машинах (см. раздел «Сведения о системе» выше) все еще сбрасывает потребление памяти моим процессом R после примерно 180 - 350 итераций (в зависимости от ОС и ОЗУ).
Там все еще наблюдается очевидное увеличение потребления памяти, и, хотя, глядя на цифры, оно может показаться не таким уж большим, мои R-процессы всегда в какой-то момент умирают из-за этого.
Ниже я опубликовал несколько временных рядов, которые явились результатом запуска моего примера на 32-битной коробке WinXP с 2 ГБ ОЗУ:
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
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
Сообщение об ошибке, связанное с 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)24,14 24,47 20,1 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 файл и сохранить его как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
которыйдолжен быть1
в обоих звонках. Фактически, именно на всех машинах Duncan проверил это. Однако, как выясняется,counter.2
имеет значение259
на всех моих машинах (см. подробности выше), и это именно то, что вызывает мою проблему.