Le traitement des fichiers XML dans PHP est une tâche courante, et XML_Parse () est une fonction courante pour le traitement de ces données. Mais face à des fichiers XML super grands (comme des dizaines de mégaoctets ou même des centaines de mégaoctets), le goulot d'étranglement des performances sera exposé. Cet article explorera en profondeur le principe de xml_parse () et plusieurs stratégies pour l'optimiser lorsqu'ils traitent avec des fichiers XML super grands.
La fonction XML_PARSE () repose sur un analyseur XML basé sur des événements (c'est-à-dire Expat). Bien qu'il fonctionne bien dans les fichiers XML petits ou moyens, les problèmes suivants peuvent se produire lorsque vous travaillez avec de grands fichiers XML:
Énorme consommation de mémoire
Vitesse d'analyse lente
Utilisation élevée du processeur
Le blocage des E / S provoque la réponse du système
La plupart des problèmes peuvent être attribués aux points suivants:
La lecture de l'ensemble du fichier XML crée à la fois une pression de mémoire.
La logique de traitement est trop centralisée ou synchronisée pour utiliser pleinement le streaming.
La fonction de rappel est mal gérée, ce qui entraîne un gaspillage de performances.
Aucune ressource d'analyseur n'a été nettoyée ou réutilisée.
Au lieu de charger l'ensemble du fichier XML à la fois, il est préférable d'utiliser Fopen et Fread pour lire le contenu XML en morceaux, et de ne nourrir qu'une petite partie du contenu à l'analyseur à la fois.
$parser = xml_parser_create();
xml_set_element_handler($parser, "startElement", "endElement");
xml_set_character_data_handler($parser, "characterData");
$fp = fopen("https://m66.net/files/large-xml-file.xml", "r");
if (!$fp) {
die("Impossible d'ouvrir XML document");
}
while ($data = fread($fp, 4096)) {
if (!xml_parse($parser, $data, feof($fp))) {
die(sprintf("XML erreur: %s Dans le processus %d",
xml_error_string(xml_get_error_code($parser)),
xml_get_current_line_number($parser)));
}
}
xml_parser_free($parser);
fclose($fp);
L'avantage est que l'empreinte de la mémoire est toujours contrôlable, et même si le fichier est grand, il ne chargera pas tout le contenu à la fois.
L'efficacité d'exécution de la fonction de rappel enregistrée affecte directement la vitesse d'analyse globale. Essayez d'éviter d'effectuer une logique complexe ou des opérations d'E / S lentes fréquentes telles que les bases de données et les disques dans les rappels.
function startElement($parser, $name, $attrs) {
// Logique simplifiée,Évitez un jugement ou une nidification supplémentaire
if ($name === "ITEM") {
// Enregistrer uniquement les champs de données requis
global $currentItem;
$currentItem = [];
}
}
function characterData($parser, $data) {
global $currentItem;
$data = trim($data);
if (!empty($data)) {
$currentItem[] = $data;
}
}
function endElement($parser, $name) {
global $currentItem;
if ($name === "ITEM") {
// Résultats de traitement ou d'économie de cache de retard
// saveToDatabase($currentItem); // Le traitement asynchrone ou par lots est meilleur
// Exemple de code de traitement:
file_put_contents("/tmp/parsed-items.log", json_encode($currentItem) . "\n", FILE_APPEND);
}
}
L'utilisation continue de xml_parse () peut provoquer des problèmes de mémoire non décédés. Assurez-vous d'utiliser xml_parser_free () pour libérer l'analyseur et effacer les variables globales si nécessaire.
Bien que XML_PARSE convient à l'analyse mobilière de PHP, XMLReader fournit une manière plus moderne, prend également en charge la lecture en streaming et est plus contrôlable.
$reader = new XMLReader();
$reader->open("https://m66.net/files/large-xml-file.xml");
while ($reader->read()) {
if ($reader->nodeType == XMLReader::ELEMENT && $reader->name == "item") {
$node = $reader->readOuterXML();
// traiter avec item nœud
}
}
$reader->close();
Afin de quantifier l'effet d'optimisation, il est recommandé d'utiliser la méthode suivante pour les tests:
Utilisez Memory_get_Usage () et MicroTime () pour enregistrer la mémoire et la consommation de temps
Appels du système de suivi et goulot d'étranglement avec Strace ou Xdebug
Comparaison de la différence d'occupation des ressources entre le chargement ponctuel et le traitement de la chasse
Lors du traitement des fichiers XML super grands, la clé pour optimiser XML_Parse () est " Contrôler l'utilisation des ressources + la logique de traitement de rationalisation ". Il est recommandé de hiérarchiser l'utilisation de la lecture en morceaux et des rappels minces, puis envisagez d'utiliser des outils d'analyse plus puissants tels que XMLReader au besoin.
Combinaison recommandée:
Pour les tâches générales: xml_parse () + fread () + simplification de rappel
Pour une grande analyse des données: XMLReader + Traitement de retard + enregistrement par lots
Grâce à une optimisation raisonnable, un processus d'analyse efficace et stable peut être réalisé même lorsqu'il est confronté à des centaines de MB de fichiers XML.