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