IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage PHP Discussion :

Fuites mémoires ?


Sujet :

Langage PHP

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Juillet 2009
    Messages
    112
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2009
    Messages : 112
    Points : 64
    Points
    64
    Par défaut Fuites mémoires ?
    Bonjour,

    J'ai un "drôle" de soucis. Je dois traiter des fichiers. Je fais donc une boucle dessus. Lorsqu'il n'y en a pas beaucoup à traiter, tout va bien. Mais lorsque j'ai beaucoup de fichiers, ma boucle ralenti petit à petit et je vois la mémoire qui augmente.

    Pour exemple, au début ma boucle traite 200 fichiers/s mais à l'approche du 2000e, elle ne traite plus qu'un fichier à la seconde. Au delà, ça ralentir encore et toujours. En même temps, je vois la RAM qui monte.

    A chaque tour de boucle, toutes les variables ou objets que j'utilise sont réaffectées, je suppose donc que PHP est censé nettoyer la mémoire et virer les anciennes affectations.

    Mais je ne sais pas comment vérifier cela, ni comment tracer ce genre de phénomène.

    Quelqu'un peut-il m'aider ?

    Merci par avance !!

  2. #2
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2013
    Messages
    72
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2013
    Messages : 72
    Points : 68
    Points
    68
    Par défaut
    Salut!

    Alors je suis pas sûre à 100% de ce que je dis mais à mon avis à chaque passage dans ta boucle, si tu traite le fichier, il est chargé en ram ce qui la rempli de plus en plus jusqu'à la saturer.

    Est-ce que, dans ta boucle, tu supprime la connection au fichier après l'avoir traité? (peut être chercher du côté de la fonction "fclose" )

    PS: Si tu peux nous passer ton code, ça nous aiderait à comprendre où se trouve le problème..

  3. #3
    Membre éprouvé Avatar de Shuty
    Homme Profil pro
    Ingénieur en développement
    Inscrit en
    Octobre 2012
    Messages
    630
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur en développement
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Octobre 2012
    Messages : 630
    Points : 1 174
    Points
    1 174
    Par défaut
    De manière personnel, j'évite de faire de gros traitement en PHP. Je préfère faire un appel sur un autre dev via un exec();

    Un benchmark plutot intéressant :
    http://herverenault.fr/comparaison-l...programmation/

    La vitesse d’exécution et la gourmandise en RAM peu être corriger en allégeant / corrigeant la logique du code. Le benchmark est donc relatif.
    Agence web Dim'Solution, créateur de solutions numériques
    Sites internet, ecommerce, logiciels, applications mobiles, référencement (SEO), plugin Prestashop, Magento, WordPress, Joomla!...

    Cours de trading gratuit | Envoyer des sms gratuitement | Envoyer des fax gratuitement | Plateforme de Fax à l'international

  4. #4
    Membre du Club
    Profil pro
    Inscrit en
    Juillet 2009
    Messages
    112
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2009
    Messages : 112
    Points : 64
    Points
    64
    Par défaut
    @Shuty : Pour tout avouer, un traitement extarne ne m'arrange pas trop même si je conçoit qu'en effet PHP n'est pas trop fait pour les gros traitements.

    @jurta : je n'utilise pas de fopen ni de fclose, mais plutôt des classes de chargement de contenu fichiers xml.

    Voici le code "allégé" contenant les parties d'affectations de variables :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    for ($i = 0; $i < $nb_docs; $i++) { // Boucle sur l'ensemble des fichiers
            $filepath = $ar_docs[$i];
            $path_parts = pathinfo($filepath);
            set_time_limit(30);
     
            $document = new DOMDocument;
            if (@$document->loadHTMLFile($filepath) === FALSE) { // Chargement du contenu du fichier
                $logger->addDebug('Cannot load this HTML file');
            } else {
                $xpath = new DOMXPath($document);
     
                // Pour chaque balise <style> contenues dans le document, récupération des selecteurs
                // afin de mettre à jour les balises correspondantes
                $entries = $xpath->query('//html/head/style');
                foreach ($entries as $entry) :
                    $matches = NULL;
                    if (preg_match_all('/(?<selector>.*){(?<content>.*)}/', $entry->nodeValue, $matches, PREG_SET_ORDER)) :
                        foreach ($matches as $matche) :
     
                            // Transformation d'un selecteur CSS en expression XPath en utilisant
                            // la bibliothèque Zend
                            $domQuery = new Zend_Dom_Query_Css2Xpath();
                            $xpathQuery = $domQuery->transform($matche[1]);
                            foreach ($xpath->query($xpathQuery) as $result) :
                                $attributes = array();
                                if ($result->hasAttribute('style')) :
                                    $attributes[] = rtrim($result->getAttribute('style'), ';');
                                endif;
                                $attributes[] = $matche[2];
                                $result->setAttribute('style', implode(';', $attributes));
                            endforeach;
     
                        endforeach;
                    endif;
                endforeach;
     
    			// Titre du courrier
                $title = $path_parts['filename'];
     
                // Enregistrement du courrier dans la base de données
                foreach ($users as $user) {
                    $letterEntity = new Entities\Letters;
                    $letterEntity->setUser($user);
                    $letterEntity->setTitle($title);
                    $letterEntity->setMsg($document->saveHTML($xpath->query('//html/body')->item(0)));
                    $letterEntity->setType('contact');
                    if (!empty($contactEntity))
                        $letterEntity->setContact($contactEntity);
                    $entityManager->persist($letterEntity);
                    $entityManager->flush();
                }
                // Courrier enregistré en base de données : on supprime le fichier
                @unlink($filepath);
            }
        }
    Merci encore pour votre aide !!

  5. #5
    Modérateur
    Avatar de grunk
    Homme Profil pro
    Lead dév - Architecte
    Inscrit en
    Août 2003
    Messages
    6 691
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Lead dév - Architecte
    Secteur : Industrie

    Informations forums :
    Inscription : Août 2003
    Messages : 6 691
    Points : 20 222
    Points
    20 222
    Par défaut
    Tu peux commencer à débugger en utilisant memory_get_usage et memory_get_peak_usage

    Après dans ton cas si tu as beaucoup de fichier à traiter et surtout si il sont de grosse taille il sera plus performant de passer par un parseur SAX plutôt que DomDocument et xpath.
    Pry Framework php5 | N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  6. #6
    Membre du Club
    Profil pro
    Inscrit en
    Juillet 2009
    Messages
    112
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2009
    Messages : 112
    Points : 64
    Points
    64
    Par défaut
    @grunk : non ce ne sont que de petits fichiers qui font tous moins de 40Ko.
    Je vais faire des tests avec les fonctions memory_get_*.

    merci

  7. #7
    Membre éprouvé Avatar de tdutrion
    Homme Profil pro
    Architecte technique
    Inscrit en
    Février 2009
    Messages
    561
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Architecte technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2009
    Messages : 561
    Points : 1 105
    Points
    1 105
    Par défaut
    Je vais probablement dire une betise car je ne suis pas du tout specialiste de l'optimisation, mais je mettrais bien un unset sur le $document (ligne 6) en fin de boucle, car là je vois une masse de $document créés.

  8. #8
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2013
    Messages
    72
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2013
    Messages : 72
    Points : 68
    Points
    68
    Par défaut
    Je suis aussi de l’avis de Théocrite.. Essaie déjà de fermer chacune de tes variables que tu déclares dans tes boucles. Personnellement je vois surtout $domQuery (Zend doit bien contenir une fonction de clôture de tes variables et sinon ba unset devrait le faire aussi)

    Peut être que la solution n'y est pas mais ça peut jamais faire de mal

  9. #9
    Membre éprouvé Avatar de Shuty
    Homme Profil pro
    Ingénieur en développement
    Inscrit en
    Octobre 2012
    Messages
    630
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur en développement
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Octobre 2012
    Messages : 630
    Points : 1 174
    Points
    1 174
    Par défaut
    A priori les unset ne changeront rien au problème selon la doc:

    unset() does just what it's name says - unset a variable. It does not force immediate memory freeing. PHP's garbage collector will do it when it see fits - by intention as soon, as those CPU cycles aren't needed anyway, or as late as before the script would run out of memory, whatever occurs first.

    If you are doing $whatever = null; then you are rewriting variable's data. You might get memory freed / shrunk faster, but it may steal CPU cycles from the code that truly needs them sooner, resulting in a longer overall execution time.
    Bon à savoir:

    http://www.php.net/manual/en/feature...iderations.php
    Agence web Dim'Solution, créateur de solutions numériques
    Sites internet, ecommerce, logiciels, applications mobiles, référencement (SEO), plugin Prestashop, Magento, WordPress, Joomla!...

    Cours de trading gratuit | Envoyer des sms gratuitement | Envoyer des fax gratuitement | Plateforme de Fax à l'international

  10. #10
    Modérateur
    Avatar de sabotage
    Homme Profil pro
    Inscrit en
    Juillet 2005
    Messages
    29 208
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Juillet 2005
    Messages : 29 208
    Points : 44 155
    Points
    44 155
    Par défaut
    La doc dit seulement que la mémoire ne sera pas liberée immédiatement, mais elle sera liberée quand même.
    N'oubliez pas de consulter les FAQ PHP et les cours et tutoriels PHP

  11. #11
    Membre éprouvé Avatar de Shuty
    Homme Profil pro
    Ingénieur en développement
    Inscrit en
    Octobre 2012
    Messages
    630
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur en développement
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Octobre 2012
    Messages : 630
    Points : 1 174
    Points
    1 174
    Par défaut
    Citation Envoyé par sabotage Voir le message
    La doc dit seulement que la mémoire ne sera pas liberée immédiatement, mais elle sera liberée quand même.
    A ce que j'ai pu lire dans les autre comments, elle est libéré une fois que le script est terminer. (A vérifier)
    Agence web Dim'Solution, créateur de solutions numériques
    Sites internet, ecommerce, logiciels, applications mobiles, référencement (SEO), plugin Prestashop, Magento, WordPress, Joomla!...

    Cours de trading gratuit | Envoyer des sms gratuitement | Envoyer des fax gratuitement | Plateforme de Fax à l'international

Discussions similaires

  1. [tomcat][memoire] java.net.URL et fuite mémoire
    Par Seiya dans le forum Tomcat et TomEE
    Réponses: 6
    Dernier message: 09/03/2009, 10h41
  2. [Fuites mémoire] Je cherche un utilitaire
    Par 10_GOTO_10 dans le forum C++Builder
    Réponses: 8
    Dernier message: 10/02/2005, 10h03
  3. Outil de recherche de fuite mémoire
    Par eag35 dans le forum MFC
    Réponses: 4
    Dernier message: 02/02/2005, 12h46
  4. [SWT]SWT et fuite mémoire(ou pas)
    Par menuge dans le forum SWT/JFace
    Réponses: 2
    Dernier message: 22/06/2004, 21h40
  5. [debug] fuites mémoires
    Par tmonjalo dans le forum C
    Réponses: 3
    Dernier message: 28/07/2003, 17h20

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo