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

PHP & Base de données Discussion :

Mémoire maximale atteinte et fin de script


Sujet :

PHP & Base de données

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Homme Profil pro
    Développeur Web
    Inscrit en
    Avril 2014
    Messages
    266
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Avril 2014
    Messages : 266
    Par défaut Mémoire maximale atteinte et fin de script
    Bonjour,

    Pour une application permettant de générer des fichiers à partir de bases de données, j'ai un problème de mémoire que je n'arrive pas à résoudre. J'ai essayé d'améliorer le plus possible la gestion de la mémoire dans le script mais j'arrive à un point où je ne vois pas ce qui peut générer ce type d'erreur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Fatal error:  Allowed memory size of 536870912 bytes exhausted (tried to allocate 528384 bytes)
    Le script utilise principalement une fonction générateur permettant d'extraire des données d'une base de donnée partie par partie et je vide les variables tableaux résultats à chaque boucle, mais après plusieurs dizaines de minutes j'ai ce problème de mémoire vive.
    Je ne comprends vraiment pas pourquoi puisqu'à chaque boucle je vide les variables contenant le plus de données :

    $array=NULL;
    unset($array);
    Ca a amélioré la mémoire disponible, mais lorsque je traite 500 000 lignes par paquet de 1000, j'arrive vers la fin à ce problème de mémoire vive.

    Je ne vois pas l'utilité d'augmenter la taille maximale de mémoire vive puisque normalement le script php devrait se limiter à 200-300 Mo de données utilisées/détruites environ.

    Pourriez vous m'indiquer si il existe un moyen sûr de limiter au minimum l'utilisation de la mémoire vive du script PHP ?

    Merci.

  2. #2
    Membre éclairé
    Homme Profil pro
    Développeur Web
    Inscrit en
    Avril 2014
    Messages
    266
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Avril 2014
    Messages : 266
    Par défaut
    Peut être en rapport avec le problème de mémoire, le script a fini par se figer (en ligne de commande) après avoir fait une requête sur la base Mysql... plus rien ne s'affiche... La requête en elle même ne pose aucun problème visiblement c'est php...

  3. #3
    Membre très actif
    Profil pro
    Administrateur
    Inscrit en
    Mai 2008
    Messages
    237
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Administrateur
    Secteur : Industrie

    Informations forums :
    Inscription : Mai 2008
    Messages : 237
    Par défaut
    536.870912 Mo de mémoire

    Je pense que vous cherchez à traiter trop de données,
    Déjà en terme de performance, cela devrait forcement ralentir votre script.
    Pourquoi ne pas traiter des blocs plus petits, exemple 500 au lieu de 1000

    Avez-vous des appels de fonctions dans votre boucle ? Une fonction recursive par exemple ?
    Il est aussi possible que le chargement des fichiers que vous créer en mémoire puisse y être pour quelque chose.

    Difficile de vous aider sans voir le script.

  4. #4
    Expert confirmé Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 986
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 2 986
    Par défaut
    Le script utilise principalement une fonction générateur permettant d'extraire des données d'une base de données...
    Pour en faire quoi? Montre ton script.

  5. #5
    Membre éclairé
    Homme Profil pro
    Développeur Web
    Inscrit en
    Avril 2014
    Messages
    266
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Avril 2014
    Messages : 266
    Par défaut
    Bonjour,

    En ce qui concerne le blocage de script, j'ai trouvé la raison : en deux mots ma table comportait des valeurs incohérentes, donc lorsque j'interrogeais la table après une mise à jour dans une boucle (mise à jour qui en fait échouait car impossible d'après mon programme), la requête retournait toujours le même résultat .. Il était nécessaire que je supprime ces lignes qui ne devaient pas exister.

    Je vais essayer de synthétiser. J'ai une table avec des données fonctions de la date (de 1973 à 2021 ) à mettre à jour avec en moyenne une valeur toutes les 15 / 30 minutes (soit 8760*2*47=823000 enregistrement grosso modo). le processus prélève les données sources dans cette même table et dans le même temps le processus balaie toute la table pour chaque date et met à jour les lignes si celles ci sont effectivement à modifier (création ou mise à jour).
    C'est le balayage et la mise à jour de la table qui au bout d'un certain temps prend toute la mémoire allouée pour le script.
    Pour balayer toutes les lignes j'ai fait un balayage par parquet en utilisant les générateurs, ici 1 paquet = 5000 lignes et comme la base est en train d'être mise à jour l'offset initial est toujours 0 (j'ai allégé la liste des options qui rendent la lecture un peu longue) :


    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
        function retourne_tableau_bd_optim_generator($sql,$option_val)
        {
     
            $option_val["nombre_lignes_max_par_requete"]=5000; //nombr ede lignes maximum par requetes par exemple
     
            $nb_lignes=0;
            $nb_pass=0;  
     
            while($nb_lignes==$nb_pass*$option_val["nombre_lignes_max_par_requete"]){
     
    	        $sql_t=$sql." LIMIT 0,".$option_val["nombre_lignes_max_par_requete"];
     
    	        $r = mysqli_query($GLOBALS['base'],$sql_t) or exit(mysqli_error($GLOBALS['base']));
     
    	        while( $donnee = mysqli_fetch_array($r,MYSQLI_ASSOC))  {
    				$nb_lignes++;
    				yield $donnee;
    	       	}
    	       	$donnee=NULL;unset($donnee);
    	       	$nb_pass++;
    			mysqli_free_result($r);				
    		}
     
     
        return $nb_lignes;
        }

    j'appelle la fonction avec :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $raw_data_source_bd=retourne_tableau_bd_optim_generator($sql,array(""));
    Ensuite commence une boucle pour chaque valeur de dates, permettant de contrôler et mettre à jour les données.
    Dans cette boucle je lis les données de la table avec :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $raw_data_source_bd->current()["date_locale"];
    J'extrais des données "sources":
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $data=$raw_data_source_bd->current()["data_sources"];
    Ces données sont traitées pour être mise dans un tableau (1 ligne) temporaire qui servira à mettre à jour la base de données. ce tableau est ensuite détruit puis on recommence la boucle pour une nouvelle date, etc...



    Cette fonction marche parfaitement, et j'ai fait me semble-t il le max pour éviter d'occuper de façon croissante la place de la mémoire disponible.

    La question porte essentiellement sur l'utilisation d'un générateur, est ce que les données renvoyées sont stockées quelque part ? Si oui comment les supprimer périodiquement ?

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

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

    Informations forums :
    Inscription : Août 2003
    Messages : 6 693
    Par défaut
    En théorie avec un générateur tu ne consommes pas plus que ce que consomme un "tour" du générateur.

    Tu peux essayer de voir où la mémoire est "perdue" en utilisant memory_get_usage()
    Pry Framework php5 | N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Signal sonore en fin de script
    Par saih_tam dans le forum Simulink
    Réponses: 2
    Dernier message: 06/03/2009, 18h55
  2. mémoire maximale d'un programme c
    Par Invité1 dans le forum C
    Réponses: 16
    Dernier message: 26/08/2008, 20h59
  3. Libération mémoire + variable inutile en fin de code
    Par kenshi240683 dans le forum GTK+ avec C & C++
    Réponses: 2
    Dernier message: 12/06/2008, 17h44
  4. Appeler une fonction en fin de script
    Par Oprichnik dans le forum Langage
    Réponses: 4
    Dernier message: 26/08/2007, 23h42
  5. Réponses: 13
    Dernier message: 10/11/2006, 09h24

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