Мне нужно прочитать большой XML файл (~ 5,4 ГБ). Я заметил, что при анализе файла с быстрым XML используется примерно в 6 раз больше оперативной памяти, чем размер файла на диске (поэтому для анализа файла размером 200 МБ требуется ~ 1,2 ГБ ОЗУ, а для файла 5,4 ГБ потребуется ~ 32,4 ГБ ОЗУ !). Чтобы избежать обмена, я решил разделить файл на более мелкие куски и прочитать их по одному (используя инструмент xml -split из библиотеки запятая ). Я могу правильно читать и анализировать файлы XML.
Проблема: Когда я достигаю конца первого файла, я могу успешно открыть второй, но первый файл все еще использует памяти, даже если я очищаю rapidxml::document
и / или удаляю rapidxml::file<>
. Вот заголовочный файл:
//*1st code snippet*
//.h file
#include "rapidxml_utils.hpp" //Implicitly includes 'rapidxml.hpp'
...
private:
std::basic_ifstream<char> inStream;
rapidxml::file<>* sumoXmlFile;
rapidxml::xml_document<> doc;
uint16_t fcdFileIndex; //initialized at 0
...
Вот код для открытия нового XML файла:
//*2nd code snippet*
//.cc file
bool parseNextFile()
{
//check if file exists (filenames are : fcd0.xml, fcd1.xml, fcd2.xml, etc.)
struct stat buffer;
std::string fileName = std::string("fcd") + std::to_string(fcdFileIndex) + ".xml";
bool fileExists = (stat(fileName.c_str(), &buffer) == 0);
if(!fileExists)
return false;
//"increment" the name for the next file (when this method will be recalled)
fcdFileIndex++;
//open a reading stream, create the 'file' and parse it
inStream.open(fileName.c_str(), std::basic_ifstream<char>::in);
sumoXmlFile = new rapidxml::file<>(inStream);
doc.parse<0>(sumoXmlFile->data());
return true;
}
Я вызываю parseNextFile()
в коде в первый раз (для откройте 1-й файл). Затем регулярно вызывается метод update()
:
//*3rd code snippet*
void update()
{
//Read next tag
rapidxml::xml_node<>* node = doc.first_node("timestep");
//If no 'timestep' tags are left, clean and parse the next file.
if(!node)
{
doc.clear(); //**not sure**
delete sumoXmlFile; //**not sure**
inStream.close(); //**not sure**
if(parseNextFile()) //See 2nd code snippet
node = doc.first_node("timestep");
else
return;
}
//read the children nodes of the current 'timestep'
for(rapidxml::xml_node<>* veh = node->first_node(); veh; veh = node->first_node())
{
...
//read some attributes using 'veh->first_attribute("...")'
...
node->remove_first_node();
}
doc.remove_first_node();
}
Проблема заключается в (я думаю) при «очистке» (строки, помеченные как «не уверен» в предыдущем фрагменте кода). Я пробовал несколько комбинаций clear()
, delete
, вызывая деструктор memory_pool
. Ничто из того, что я пробовал, не освобождает память. Я также непосредственно открыл XML файлы с помощью
sumoXmlFile = new rapidxml::file<>(fileName.c_str()); //see 2nd code snippet
вместо создания ifstream
вручную.
Для суммирования при открытии первого XML файл, он успешно загружается и используется некоторая память. Когда я закончу с этим, я пытаюсь очистить / удалить / очистить пул памяти (без успеха) и открыть второй файл (с успехом). На этом этапе 1-й и 2-й файлы используют память. Разбор 2-го файла работает правильно (даже 3-й, 4-й и т. Д.), Но в какой-то момент ОЗУ становится довольно полным.
(наконец) Мой вопрос: Я что-то сделал неправильно освобождать память, используемую первым файлом? Можно ли освободить используемую память и прочитать следующий файл? Я не против уничтожить файлы XML в процессе, если это необходимо.
(Ради полноты: этот код на самом деле представляет собой OMNeT ++ симуляцию и файл XML генерируется SUMO . Я уверен, что файл XML не содержит ошибок.)
Спасибо за любую помощь или советы, которые могут быть предоставлены!