Серьезная утечка памяти при итеративном анализе файлов XML.

Контекст

При итерации по набору файлов Rdata (каждый из которых содержит вектор символов HTML-кода), которые загружаются, анализируются (с помощью функции XML ) и затем удаляются снова по памяти, я наблюдаю значительное увеличение Потребление памяти процессом R (в конечном итоге убивая процесс).

Это похоже на

  • освобождение объектов с помощью free () ,
  • их удаление с помощью rm () и
  • с помощью gc ()

не имеют никаких эффектов, поэтому потребление памяти накапливается до тех пор, пока не кончится память.

РЕДАКТИРОВАТЬ 13.02.2012 23:30:00

Благодаря ценной информации, предоставленной автором и сопровождающим пакета XML , Дунканом Темпл Ланг (еще раз: я очень ценю это! ) проблема, похоже, тесно связана с тем, как освобождаются внешние указатели и как выполняется сборка мусора в пакете XML. Дункан выпустил версию пакета с исправленными ошибками (3.92-0), которая объединила некоторые аспекты синтаксического анализа XML и HTML и предлагает улучшенную сборку мусора, при которой больше нет необходимости явно освобождать объект, содержащий внешний указатель, через free ( ) . Вы можете найти исходный код и двоичный файл Windows на сайте Дункана Omegahat .


РЕДАКТИРОВАТЬ 13.02.2012 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 (см. Выше). Тот факт, что это не так, кажется ошибкой (по словам Дункана).


РЕДАКТИРОВАТЬ 14.02.2012 23:12:00

Дункан разместил еще одну версию XML (3.92-1) на своем веб-сайте Омегахат Веб-сайт Омегахат . Это должно решить проблему в целом. Однако мне, похоже, не повезло с моим примером, поскольку я все еще испытываю ту же утечку памяти.


РЕДАКТИРОВАТЬ 2012-02-17 20:39:00> РЕШЕНИЕ!

ДА! Дункан нашел и исправил ошибку! Это была небольшая опечатка в сценарии только для Windows, объясняющая, почему ошибка не проявляется в Linux, Mac OS и т. Д. Посмотрите последнюю версию 3.92-2.! Потребление памяти теперь настолько постоянное, насколько это возможно при итеративном синтаксическом анализе и обработке файлов XML!

Особая благодарность еще раз Дункану Темплу Лангу и всем остальным, кто ответил на этот вопрос!


>>> УСТАРЕВШИЕ ЧАСТИ ОРИГИНАЛЬНОГО ВОПРОСА

Пример инструкции (отредактировано 14.02.2012 15:00:00)

  1. Загрузите папку 'memory' из моего Репозиторий Github .
  2. Откройте скрипт ./ scripts / memory.R и установите а) ваш рабочий каталог в строку 6 , б) пример область в строке 16 , а также c) принудительно ли освобождать проанализированный документ в строке 22 . Обратите внимание, что вы все еще можете найти старые сценарии; они «помечены» знаком « LEGACY » в конце имени файла.
  3. Запустить сценарий.
  4. Изучите последний файл ./ memory_ .txt , чтобы увидеть увеличение регистрируемых состояний памяти с течением времени. Я включил два текстовых файла, полученных в результате моих собственных тестовых прогонов.

То, что я сделал в отношении управления памятью

  • , убедившись, что загруженный объект снова удаляется с помощью rm () в конце каждой итерации.
  • При синтаксическом анализе файлов XML я установил аргумент addFinalizer = TRUE , удалил все объекты R, которые имеют ссылку на проанализированный XML-документ, прежде чем освободить указатель C с помощью free () и удаление объекта, содержащего внешний указатель.
  • добавление gc () туда и сюда.
  • пытается следовать совету из заметок Дункана Темпла Ланга по управлению памятью при использовании его пакета XML (хотя я должен признать, что не полностью понял, что там написано)

РЕДАКТИРОВАТЬ 2012-02 -13 23:42:00: Как я указал выше, явные вызовы free (), за которым следует rm () , больше не нужны, поэтому я прокомментировал эти вызовы.

Информация о системе

  • 32-разрядная Windows XP, 4 ГБ ОЗУ
  • 32-разрядная Windows 7, 2 ГБ ОЗУ
  • 64-разрядная Windows 7, 4 ГБ ОЗУ
  • R 2.14.1
  • XML 3.9 -4
  • XML 3.92-0, найденный на http://www.omegahat.org/RSXML/

Первоначальные результаты по состоянию на 09.02.2012, 01:00:00

  1. Запуск веб-сканирования сценарий на нескольких машинах (см. раздел «Информация о системе» выше) всегда прерывает потребление памяти моим процессом R примерно после 180 - 350 итераций (в зависимости от ОС и ОЗУ).
  2. Выполнение простого сценария rdata приводит к постоянному потреблению памяти тогда и только тогда, когда вы устанавливаете явный вызов сборщика мусора через gc () на каждой итерации; в противном случае вы испытаете то же поведение, что и в сценарии просмотра веб-страниц.

Вопросы

  1. Есть идеи, что вызывает увеличение памяти?
  2. Есть идеи, как обойти это?

Результаты по состоянию на 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

Edit 2012-02-17: пожалуйста, помогите мне проверить значение счетчика

Вы окажете мне огромную услугу, если сможете запустить следующий код. Это займет не более 2 минут вашего времени . Все, что вам нужно сделать, это

  1. загрузить файл Rdata и сохранить его как seed.Rdata .
  2. Загрузите сценарий, содержащий мою функцию очистки , и сохраните его как scrape.R .
  3. Создайте следующий код после соответствующей настройки рабочего каталога.

Код:

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 на всех моих машинах (см. Подробности выше), и это именно то, что вызывает мою проблему.

14
задан 27 revs, 2 users 100% 17 February 2012 в 19:52
поделиться