[RESOLU] Limite de mémoire

Petit nouveau ! | 6 Messages

08 juin 2016, 16:55

Bonjour
Je pose ma question ici car vous aviez répondu à une question similaire il y a quelques années car le cas de quelqu'un qui souhaitait savoir comment augmenter la mémoire allouée à son script.
En réalité, moi je cherche plutôt dans un premier temps à réduire la taille de mon script.
Un script qui extrait des infos d'une table mysql pour le sortir en xml. Il y a environ 60000 entrées dans la table. Le script bloque à 21000.

Je ne vois pas comment réduire les ressources qu'utilise mon script, si vous avez la moindre idée, je vous écoute.

Voici le code

Code : Tout sélectionner

<?php function xmlentities($text){ $search = array('&','<','>','"','\''); $replace = array('&','<','>','"','&apos;'); $text = str_replace($search,$replace,$text); return $text; } /* On génère le flux */ set_time_limit(0); $nb_page = 0; $date = date("Y-m-d"); $base = "https://www.monsite.fr/"; //Entete XML; $xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"."\n"; $xml.= "<Mitula>"."\n"; //Recherche de tous les biens en vente $sql = "SELECT [MES COLONNES] FROM [MA TABLE 1 ] as a INNER JOIN [MA TABLE 2 ] AS m ON [COL] = [COL] INNER JOIN [MA TABLE 3 ] AS d ON [COL] = [COL] INNER JOIN [MA TABLE 4 ] AS c ON [COL] = [COL] WHERE [COL] = 1 and [COL] >= '".$date."' or [COL] = '0000-00-00' ORDER BY [COL] DESC , [COL] DESC"; $result = $pdo->query($sql)->fetchAll(); foreach($result as $row){ $lienBien = rewriteUrl('annonce', $row['[COL] '], $pdo); $id=$row['[COL] '] ; $title=$row['[COL] '] ; $idtype=$row['[COL] '] ; if ($idtype == 1 or $idtype == 2 or $idtype == 3) { $type = "Sale" ; } else if ($idtype == 5) { $type = "SALE" ; } else { $type = "PG" ; } $content=$row['[COL] '] ; if ($idtype == 1) { $property_type = "A" ; } else if ($idtype == 2) { $property_type = "M" ; } else if ($idtype == 3) { $property_type = "I" ; } else if ($idtype == 5) { $property_type = "LC" ; } else if ($idtype == 6) { $property_type = "PG" ; } else { $property_type = "" ; } $floor_area=$row['[COL] '] ; $city = $row['[COL] '] ; $long = $row['[COL] '] ; $lat = $row['[COL] '] ; $region = $row['[COL] '] ; $city_area=$row['[COL] '] ; $idrooms = $row['[COL] '] ; if ($idrooms == 1) { $rooms = 1 ; } else if ($idrooms == 2 or $idrooms == 21) { $rooms = 2 ; } else if ($idrooms == 3 or $idrooms == 22) { $rooms = 3 ; } else if ($idrooms == 4 or $idrooms == 23) { $rooms = 4 ; } else if ($idrooms == 5 or $idrooms == 24) { $rooms = 5 ; } else if ($idrooms == 25) { $rooms = 6 ; } else { $rooms = "" ; } $price=$row['[COL] '] ; $postcode=$row['[COL] '] ; $address=$row['[COL] '] ; //$picture_url=$row['[COL] '] ; $parking=$row['[COL] '] ; $virtual_tour=$row['[COL] '] ; $date=$row['[COL] '] ; $plot_area=$row['[COL] '] ; if ($row['[COL] '] == 1) {$is_furnished=1;} else {$is_furnished=0;} if ($row['[COL] '] > '2012-01-01') {$is_new=1;} else {$is_new=0;} //$condition=$row['[COL] '] ; if ($row['[COL] '] != '0000-00-00') {$year=substr($row['[COL] '], 0, -6) ;} $agency = $row['[COL] '] ; if ($row['[COL] '] == 1) {$by_owner = 1;} if ($row['[COL] '] > 0) { $rnz = $row['[COL] '] ; $note = "Note" ; } else { $rnz = "" ; $est = "" ; } $tabPhoto = photoAnnonce($pdo,$row['[COL]']); $xml.= "<ad>"."\n"; $xml.= "<id><![CDATA[".$id."]]></id>"."\n"; $xml.= "<url><![CDATA[".$base.xmlentities($lienBien)."]]></url>"."\n"; $xml.= "<title><![CDATA[".$title."]]></title>"."\n"; $xml.= "<type><![CDATA[".$type."]]></type>"."\n"; $xml.= "<content><![CDATA[".$rnz.$content.$note."]]></content>"."\n"; $xml.= "<property_type><![CDATA[".$property_type."]]></property_type>"."\n"; $xml.= "<floor_area><![CDATA[".$floor_area."]]></floor_area>"."\n"; $xml.= "<city><![CDATA[".$city."]]></city>"."\n"; $xml.= "<city_area><![CDATA[".$city_area."]]></city_area>"."\n"; $xml.= "<region><![CDATA[".$region."]]></region>"."\n"; $xml.= "<rooms><![CDATA[".$rooms."]]></rooms>"."\n"; $xml.= "<latitude><![CDATA[".$lat."]]></latitude>"."\n"; $xml.= "<longitude><![CDATA[".$long."]]></longitude>"."\n"; $xml.= "<price><![CDATA[".$price."]]></price>"."\n"; $xml.= "<postcode><![CDATA[".$postcode."]]></postcode>"."\n"; $xml.= "<address><![CDATA[".$address."]]></address>"."\n"; $xml.= "<pictures>"."\n"; foreach($tabPhoto as $unePhoto){ if($row['[COL] '] == 1) {$idpic = $unePhoto['[COL] '] ; } else if($row['[COL] ']>"44692" && $row['[COL] '] != 1) {$idpic = $unePhoto['[COL] '] ; } else {$idpic = $unePhoto['[COL] '];} $pic = "imagesClients/".$idpic ; $xml.= "<picture>"."\n"; $xml.= "<picture_url><![CDATA[https://www.monsite.fr/".$pic."]]></picture_url>"."\n"; $xml.= "</picture>"."\n"; } $xml.= "</pictures>"."\n"; $xml.= "<parking><![CDATA[".$parking."]]></parking>"."\n"; $xml.= "<agency><![CDATA[".$agency."]]></agency>"."\n"; $xml.= "<virtual_tour><![CDATA[".$virtual_tour."]]></virtual_tour>"."\n"; $xml.= "<date><![CDATA[".$date."]]></date>"."\n"; $xml.= "<plot_area><![CDATA[".$plot_area."]]></plot_area>"."\n"; $xml.= "<is_furnished><![CDATA[".$is_furnished."]]></is_furnished>"."\n"; $xml.= "<is_new><![CDATA[".$is_new."]]></is_new>"."\n"; //$xml.= "<condition><![CDATA[".."]]></condition>"."\n"; $xml.= "<year><![CDATA[".$year."]]></year>"."\n"; $xml.= "<by_owner><![CDATA[".$by_owner."]]></by_owner>"."\n"; $xml.= "</ad>"."\n"; $nb_page++; } unset($sql,$result,$row); $xml .= '</flux>'; // On écrit le nouveau contenu $monfichier = fopen('/mon/dossier/flux.xml', 'w+'); fputs($monfichier, $xml); fclose($monfichier); ?>

Eléphant du PHP | 176 Messages

08 juin 2016, 17:01

Bonjour Soca,

A défaut d'allouer plus de ressources au script, tu peux augmenter le temps maximal autorisé pour son exécution.

Pour cela set_time_limit ou ini_set

http://php.net/manual/fr/function.set-time-limit.php
http://php.net/manual/fr/function.ini-set.php

Il est déconseillé de mettre un temps illimité à un script !
Cordialement
Naroth

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 10684 Messages

08 juin 2016, 18:22

Ton code est plutôt simple et je ne vois pas beaucoup d'axe d'optimisation...

Je ne sais pas si cela aurait un effet, mais ça peut être intéressant de faire le test pour comparer : au lieu de tout stocker dans une variable et d'inscrire ensuite celle-ci dans ton fichier, tu pourrais essayer d'écrire dans le fichier au fur et à mesure et éviter l'alimentation de la variable.
En gros ouvrir ton fichier dès le début et faire des fputs() directement au lieu des $xml.=

Pas sur que ça change quoi que ce soit, ni que ça soit pas plus lourd, mais sur le papier, ça me semblerait logique que tu y gagnes un peu en ressources :)
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

Petit nouveau ! | 6 Messages

08 juin 2016, 19:15

Bonsoir,
Merci pour vos réponses
Pareil le script est simple, je ne vois pas non plus comment l'améliorer mais comme je débute... on sait jamais.
Ok, je vais essayer set_time_limit ou ini_set ou alors ce sera une modif du script.
Merci

ViPHP
ViPHP | 928 Messages

09 juin 2016, 01:41

Une optimisation simple et radicale pour commencer, tu remplaces :
$result = $pdo->query($sql)->fetchAll();

foreach($result as $row){
par
$stmt= $pdo->query($sql);
while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)){
ce qui fait qu'au lieu de charger tes 60K résultats en mémoire, tu les charges 1 par 1 et donc peu importe ton nombre d'enregistrement, ça consommera toujours seulement la mémoire pour un seul résultat.

Ensuite, comme le suggère Ryle, il te suffit d'écrire ton XML au fur et à mesure avec fwrite() au lieu de tout stocker dans une variable pour tout écrire à la fin.

++

Petit nouveau ! | 6 Messages

09 juin 2016, 11:16

Ah génial. C'est vrai que j'avais entendu que while consommait moins que foreach.
Je m'occupe de ça et je regarde ce que ça donne.
Je vous tiens informés.
Merci

Petit nouveau ! | 6 Messages

14 juin 2016, 08:59

C'est parfait, ça fonctionne beaucoup mieux avec vos modifications!
Un grand merci.