Спарсить большой XML файл.

[Удален]
912

Мне нужно спарсить большие XML файлы размером от ~ 500 до ~ 1700 мб.

Собственно я и юзаю XMLReader (XMLParser достал уже) а по факту они одно и тоже получается только что XMLReader удобнее юзать.

Для хранения спарсенных данных юзаю MongoDB.

Скрипт много раз уже переписывал и по разному. Вообщем проблема в том, что течет память.

xmlreader.php


<?php

$start_time = microtime(true);

include 'inc/Misc.php';

logAdd('Script start');

set_time_limit(0);

// Try to enable garbage collection on 5.3+
if (function_exists('gc_enable') && !gc_enabled()) {
gc_enable();
}

//$mongo = new Mongo();
$db = 'tess';
$collection = 'apc';


$files = array(/*'xml/apc101231-42.xml',*/
/*'xml/apc110101.xml'*/ 'xml/apc110101.xml');

foreach($files as $file) {
echo "\n";
echo 'Filename: '.basename($file)."\n";
echo 'Start parsing...'."\n";
echo "\n";


$reader = new XMLReader();

$reader->open($file);

logAdd('Srart parsing');

while ($reader->read()) {
switch ($reader->nodeType) {
case (XMLREADER::ELEMENT):
if ($reader->localName == "case-file") {

logAdd('case-file found');

$dom = new DomDocument();
$n = $dom->importNode($reader->expand(),true);
$dom->appendChild($n);
$sxe = simplexml_import_dom($n);

logAdd('case-file in $sxe');

// Insert data!
//$mongo->$db->$collection->insert($sxe);

logAdd('Insert done!');

//print_r($sxe);
echo "Insert done! \n";

// Now clear the memory.
unset($n, $dom, $sxe);

logAdd('Clear the memory');
}
break;
}
logAdd('case-file in $sxe');
}

// Close the resource
$reader->close();

// Delete the object to free memory
unset($reader);

logAdd('Stop parsing');
}

$mongo->close();

inc/Misc.php


<?php


/**
* Convert bytes in 'kb','mb','gb','tb','pb'
* @param integer $size Data to convert
* @return string
*/
function convert($size) {
$unit=array('b','kb','mb','gb','tb','pb');
return @round($size/pow(1024,($i=floor(log($size,1024)))),2).' '.$unit[$i];
}


/**
* Get memory usage
* @param boolean $render Displays the result of the function in the browser or not
*/
function getMemoryUsage($render=true) {
if (function_exists('memory_get_usage')) {
$memory_usage = memory_get_usage();
} else if (substr(PHP_OS,0,3) == 'WIN') {
// Windows 2000 workaround
$output = array();
exec('pslist ' . getmypid() , $output);
$memory_usage = trim(substr($output[8],38,10));
} else {
$memory_usage = '';
}
if($render) {
printf('Memory usage: '.convert($memory_usage));
} else {
return $memory_usage;
}
}


/**
* Get elapsed time
* @global integer $start_time Start time value
* @param boolean $render Displays the result of the function in the browser or not
*/
function getElapsedTime($render=true) {
global $start_time;
$result_time = microtime(true) - $start_time;
if($render) printf("Elapsed time %.3f seconds",$result_time); else return sprintf("%.3f", $result_time);
}


/**
* Benchmark
*/
function benchmark() {
getMemoryUsage(); echo " - "; getElapsedTime(); echo "\n";
}


/**
* Log add
*/
function logAdd($message) {
file_put_contents('log.txt',$message.' - '.convert(getMemoryUsage(false))." - ".getElapsedTime(false)."\n", FILE_APPEND);
}

?>

прологировал:

Script start - 338.05 kb - 0.003
Start parsing - 348.74 kb - 0.044
case-file found - 348.77 kb - 0.055
case-file in $sxe - 349.78 kb - 0.068
Insert done! - 422.3 kb - 0.078
Clear the memory - 349.45 kb - 0.082
case-file found - 349.44 kb - 0.302
case-file in $sxe - 350.19 kb - 0.308
Insert done! - 385.02 kb - 0.314
Clear the memory - 349.45 kb - 0.319
case-file found - 349.44 kb - 0.385
case-file in $sxe - 350.19 kb - 0.390
Insert done! - 368.86 kb - 0.395
Clear the memory - 349.45 kb - 0.401
case-file found - 349.44 kb - 0.437
case-file in $sxe - 350.19 kb - 0.441
Insert done! - 366.63 kb - 0.447
Clear the memory - 349.45 kb - 0.452
case-file found - 349.44 kb - 0.489
case-file in $sxe - 350.19 kb - 0.494
Insert done! - 367.61 kb - 0.499
Clear the memory - 349.45 kb - 0.502
case-file found - 349.44 kb - 0.539
case-file in $sxe - 350.19 kb - 0.543
Insert done! - 369.81 kb - 0.550
Clear the memory - 349.45 kb - 0.553
case-file found - 349.44 kb - 0.593
case-file in $sxe - 350.19 kb - 0.596
Insert done! - 366.64 kb - 0.602
Clear the memory - 349.45 kb - 0.607
case-file found - 349.44 kb - 0.641
case-file in $sxe - 350.19 kb - 0.646
Insert done! - 369.09 kb - 0.650
Clear the memory - 349.45 kb - 0.655

не вижу ни каких проблем, но процесс расходует память.

SJ
На сайте с 16.03.2008
Offline
78
#1

Код процессинга XML - в отдельный файл.

Его дергать например curl в цикле foreach($files as $file) для каждого файла.

Одновременно 10 потоков, например.

Любимый хостинг (http://beget.ru?id=2902) How can we grow old when the soundtrack of our lives is rock-n-roll?
[Удален]
#2

Запустил скрипт на линуксе(правда без Монги) все отлично! спарсило намного быстрее и потребило оперативки 1 метр! на 400 метров xml файла. Вообщем завтра еще с монгой проверю. А в винде жрет не мерено памяти, жирная утечка в Винде

Авторизуйтесь или зарегистрируйтесь, чтобы оставить комментарий