Сбой выделения памяти: увеличение лимита доступа к набору узлов с помощью пакета xml2

#r #libxml2 #xml2

#r #libxml2 #xml2

Вопрос:

Я анализирую некоторые очень большие XML-файлы, используя пакет xml2 в R. read_xml () успешно загружает большой файл, но когда я пытаюсь использовать xml_find_all (), я получаю «Ошибка: сбой выделения памяти: увеличение лимита доступа к набору узлов». Я предполагаю, что этот предел установлен в libxml2, возможно, в переменной XPATH_MAX_NODESET_LENGTH? так что, возможно, это не проблема с пакетом xml2 как таковым. Но возможно ли решение в xml2? Я экспериментировал с удалением узлов и освобождением памяти, но безуспешно. Спасибо.

Ответ №1:

Да, вы достигли жестко заданного предела набора узлов в движке XPath libxml2. Из xpath.c:

 /*
 * XPATH_MAX_NODESET_LENGTH:
 * when evaluating an XPath expression nodesets are created and we
 * arbitrary limit the maximum length of those node set. 10000000 is
 * an insanely large value which should never be reached under normal
 * circumstances, one would first need to construct an in memory tree
 * with more than 10 millions nodes.
 */
#define XPATH_MAX_NODESET_LENGTH 10000000
  

Одним из вариантов является перекомпиляция libxml2 с другим значением. Или вы могли бы изменить свои выражения XPath, чтобы они никогда не сталкивались с наборами узлов размером более 10 миллионов узлов. Обратите внимание, что это ограничение также применяется к промежуточным наборам узлов, созданным во время вычисления выражения. Итак, к сожалению, сегментирование набора узлов с помощью предикатов не сработает:

 //element[position() < 5000000]
//element[position() >= 5000000 and position() < 10000000]
//element[position() >= 10000000 and position() < 15000000]
  

По сути, вы должны убедиться, что каждый NodeTest возвращает не более 10 миллионов узлов. Если вы не можете этого сделать, вам, к сожалению, не повезло.

Вы также можете поднять эту проблему в списке рассылкиlibxml2. Я предполагаю, что это ограничение было введено для защиты от вредоносных выражений XPath, которые могут привести к атакам типа «отказ в обслуживании». Но, как я это вижу, выражение никогда не сможет вернуть больше узлов, чем присутствует во входных документах. Таким образом, максимальный объем памяти, используемый для набора узлов, в любом случае ограничен размером входных документов.

Комментарии:

1. Спасибо. Похоже, альтернативой является анализ событий с использованием интерфейса SAX (что я вижу, как сделать, используя функцию xmlEventParse библиотеки XML R). Не уверен, что то же самое может быть достигнуто с помощью пакета xml2 в R. . . хотя функция read_xml включает аргумент «options», который принимает «SAX1» в качестве значения . . . TBD

2. @litlogger Также должна быть возможность использовать read_xml и перемещаться по дереву документа без использования XPath. Интерфейс SAX (или XmlTextReader , если он доступен с помощью R-привязок) — это наиболее экономичный подход к использованию памяти.