2010-09-01 1 views
1

J'ai affaire à de gros fichiers XML (plusieurs mégaoctets) pour lesquels je dois faire différents types de vérifications. Cependant, j'ai un problème avec la mémoire et l'utilisation du temps qui se développe très rapidement. Je l'ai testé comme ceci:XML xpath recherche et mise en boucle de tableaux avec php, problème de mémoire

$xml = new SimpleXMLElement($string); 
$sum_of_elements = (double)0.0; 

foreach ($xml->xpath('//Amt') as $amt) { 
    $sum_of_elements += (double)$amt; 
} 

Avec microtime() et memory_get_usage() -functions je reçois les résultats suivants en exécutant ce code:

  • fichier 5Mo (7480 Amt-éléments):
    • temps d'exécution 0,69s
    • utilisation de la mémoire se développe à partir 10.25Mb à 29.75Mb

C'est encore tout à fait correct. Mais avec un peu plus la mémoire de fichiers et l'utilisation du temps se développer très bien:

  • fichier 6Mo (8976 Amt-éléments):
    • temps d'exécution 8,53s
    • Utilisation de la mémoire se développe à partir 10.25Mb à 99.25Mb

le problème semble être en boucle le jeu de résultats. J'ai aussi essayé for-loop au lieu de foreach mais sans différence. Sans boucler l'utilisation de la mémoire ne se développe pas tellement.

Une idée où le problème pourrait être?

Répondre

1

SimpleXML est basé sur l'arbre et chargera tout le document en mémoire. En utilisant unset pour marquer les ressources non nécessaires pour PHP's GC pour le nettoyage pendant une boucle might yield less memory usage. Si cela ne résout pas le problème, pensez à utiliser XMLReader pour une approche par extraction. Bien que vous ne puissiez pas utiliser XPath, la consommation de mémoire devrait être nettement inférieure.

+0

J'ai essayé de désactiver $ amt dans la boucle, mais cela n'aide pas. Quelle est la chose étrange est le grand saut entre 5mb et 6mb fichier, 5mb fichier prend seulement environ 10Mb plus de mémoire que le fichier 1Mb mais comme vous pouvez le voir, le fichier 6Mb prend déjà 60Mb plus de 5Mb fichier. – JPH

+0

Et comme je l'ai dit, la boucle semble être le problème. Si je n'enregistre que les résultats sans passer par eux ($ result = $ xml-> xpath ('// Amt')), les deux fichiers semblent prendre à peu près la même quantité de mémoire. – JPH

+2

@JPH Eh bien, vous pouvez utiliser la fonction de recherche de mémoire de XDebug ou de Zend Server pour voir où il se nourrit de votre mémoire. Vous pouvez également essayer DOM au lieu de SimpleXml pour exclure qu'il s'agit d'une fuite de mémoire dans SimpleXml. Etes-vous sûr qu'il n'y a pas d'erreurs lancées pendant la boucle? Avez-vous activé error_reporting? – Gordon