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