Контекст
При повторном запуске по набору файлов Rdata (каждый из которых содержит вектор символов HTML-кода), которые анализируются (через XML), а затем снова удалили из памяти, я ощущаю увеличение значительного R "(в конечном итоге уничтожает процесс).
Кажется, что
- освобождение объектов через
free()
, - удаляя их через
rm()
и - running
gc()
не имеют никаких эффектов, поэтому потребление памяти накапливается до тех пор, пока не останется больше памяти.
EDIT 2012-02-13 23:30:00
Благодаря ценной информации, предоставленной автором и сторонником пакета XML, Duncan Temple Lang (снова: я очень ценю это!), проблема, похоже, тесно связана с тем, как внешние указатели освобождаются и как сбор мусора обрабатывается в пакете XML. Duncan выпустил исправленную версию пакета (3.92-0), в которой были объединены определенные аспекты анализа XML и HTML, а также улучшена сборка мусора, где уже не требуется явно освобождать объект, содержащий внешний указатель, через free()
. Вы найдете исходный код и двоичный файл Windows в Duncan веб-сайт Omegahat.
EDIT 2012-02-13 23:34:00
К сожалению, новая версия пакета по-прежнему не исправляет проблемы, с которыми я сталкиваюсь в маленьком примере, который я собрал. Я последовал некоторому предложению и немного упростил этот пример, упростив понимание и найти соответствующие функции, в которых, кажется, что-то не так (проверьте функции ./lib/exampleRun.R
и .lib/scrape.R
).
EDIT 2012-02-14 15:00:00
Дункан предложил попытаться принудительно освободить проанализированный документ через .Call("RS_XML_forceFreeDoc", html)
. Я включил логический переключатель в примере (do.forcefree
в script ./scripts/memory.R
), который, если установлен в TRUE
, сделает именно это. К сожалению, это привело к краху консоли R. Было бы здорово, если бы кто-то мог проверить это на своей машине! Фактически, документ должен автоматически освобождаться при использовании последней версии XML (см. Выше). Тот факт, что это не кажется ошибкой (по словам Дункана).
EDIT 2012-02-14 23:12:00
Дункан нажал еще одну версию XML (3.92-1) на свой веб-сайт Omegahat веб-сайт Omegahat. Это должно решить проблему в целом. Тем не менее, мне кажется, что мне не повезло с моим примером, поскольку я все еще испытываю те же утечки памяти.
EDIT 2012-02-17 20:39:00 > РЕШЕНИЕ!
ДА! Дункан нашел и исправил ошибку! Это была небольшая опечатка в Windows-only script, которая объясняла, почему ошибка не отображалась в Linux, Mac OS и т.д. Проверьте последнюю версию 3.92 -2.! Потребление памяти теперь столь же постоянное, как и при итеративном синтаксическом анализе и обработке XML файлов!
Особая благодарность Дункану Храм Лангу и спасибо всем, кто ответил на этот вопрос!
→ > ЗАКОНОМЕРНЫЕ ЧАСТИ ОРИГИНАЛЬНОГО ВОПРОСА < <
Примеры инструкций (отредактировано 2012-02-14 15:00:00)
- Загрузите папку 'memory' из моего Github repo.
- Откройте script
./scripts/memory.R
и установите a) ваш рабочий каталог на строке 6, b) область примера в строке 16, а также c) для принудительного освобождения анализируемого документа или нет в строке 22. Обратите внимание, что вы все равно можете найти старые сценарии; они "помечены" символом " LEGACY" в конце имени файла. - Запустите script.
- Изучите последний файл
./memory_<TIMESTAMP>.txt
, чтобы увидеть увеличение количества зарегистрированных состояний памяти во времени. Я включил два текстовых файла, которые были результатом моих собственных тестовых прогонов.
Что я делал в отношении управления памятью
- убедитесь, что загруженный объект снова удален с помощью
rm()
в конце каждой итерации. - При анализе XML файлов я установил аргумент
addFinalizer=TRUE
, удалил все объекты R, которые имеют ссылку на анализируемый XML-документ, прежде чем освободить C-указатель черезfree()
и удалить объект, содержащий внешний указатель. - добавление
gc()
здесь и там. - пытается следовать совету в Duncan Temple Lang заметкипо управлению памятью при использовании своего пакета XML (я должен признать, что я не полностью понял, что там указано)
EDIT 2012-02-13 23:42:00:
Как я уже указывал выше, явные вызовы free()
, а затем rm()
больше не нужны, поэтому я прокомментировал эти вызовы.
Информация о системе
- Windows XP 32 бит, 4 ГБ оперативной памяти
- Windows 7 32 бит, 2 ГБ оперативной памяти
- Windows 7 64 бит, 4 ГБ оперативной памяти
- R 2.14.1
- XML 3.9-4
- XML 3.92-0, найденный в http://www.omegahat.org/RSXML/
Первоначальные результаты с 2012-02-09 01:00:00
- Запуск сценария веб-каскадов на нескольких машинах (см. раздел "Сведения о системе" выше) всегда разрушает потребление памяти моего процесса R после примерно 180 - 350 итераций (в зависимости от ОС и ОЗУ).
- Запуск сценария простой rdata дает постоянное потребление памяти тогда и только тогда, когда вы устанавливаете явный вызов сборщика мусора через
gc()
на каждой итерации; иначе вы испытываете то же поведение, что и в сценарии webscraping.
Вопросы
- Любая идея, что вызывает увеличение памяти?
- Любые идеи, как обойти это?
Выводы по состоянию на 2012-02-013 23:44:00
Запуск примера в ./scripts/memory.R
на нескольких машинах (см. раздел "Сведения о системе" выше) по-прежнему разрушает потребление памяти моего процесса R примерно после 180 - 350 итераций (в зависимости от ОС и ОЗУ).
По-прежнему наблюдается очевидное увеличение потребления памяти, и хотя это может показаться не таким уж большим, просто глядя на цифры, мои R-процессы всегда умирают в какой-то момент из-за этого.
Ниже я опубликовал пару временных рядов, которые появились в результате запуска моего примера в битве WinXP 32 бит с 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 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 и сохраните его как
seed.Rdata
. - Загрузите script, содержащий мою функцию соскабливания и сохраните ее как
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
на всех моих машинах (см. Подробности выше) и точно, что вызывает мою проблему.