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 :

Boucles sur file_get_contents et file_put_contents de plus en plus lentes


Sujet :

Langage PHP

  1. #1
    Membre éclairé
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    581
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2006
    Messages : 581
    Par défaut Boucles sur file_get_contents et file_put_contents de plus en plus lentes
    Bonjour,

    J'ai besoin de construire des fichiers JSON à partir d'un traitement de plusieurs fichiers en entrée
    Pour 1 cas, le modèle est le suivant : 10 JSON en entrée (layers) -> traitement -> 1 JSON en sortie.
    J'ai un premier lot de 19 000 cas.

    Lors du démarrage du script, les fichiers sont traités très rapidement (2 voire 3 cas par seconde), mais au fur et à mesure de l'avancée, le script est de plus en plus lent, comme si il saturait, et il faut vers la fin plusieurs dizaines de secondes pour traiter un seul cas, donc 10 fichiers. Voici la structure de mon script. Avez-vous une idée de ce que je pourrais améliorer pour éviter cette saturation ?

    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
    function IsJSONValid($json) {
    	$string = json_decode(file_get_contents($json), true);
    	$key = array_keys($string); // Clé dynamique en cas de changement de structure du JSON
    	if (count($string[$key[0]]) > 0) {
    		return true;
    	} else {
    		return false;
    	}
    }
     
    foreach ($cas_tab as $cas) {
    	$json_export = "{\"MyJSON\":[";
    	$parameters = array();
    	$file_output = 'MYJSON_'.$cas.'.json';
     
    	foreach ($layers_tab as $layers) {
    		$file_input = 'JSON'.$layers.'.json';
     
    		if (file_exists($file_input) && IsJSONValid($file_input)) {
    			$json = file_get_contents($file_input);
    			$json_content = json_decode($json, true);
    			$json_key = array_keys($json_content);
     
    			foreach ($json_content[$json_key[0]] as $value) {
    				// Traitements
    				// $parameters[$id] = ...
    			}
    		}
    	}
     
    	$json_export .= json_encode($parameters);
    	$json_export .= "]}";
    	if (count($parameters) > 0) {
    		echo "\r\n[ ".count($parameters)." IDs traités ] Génération du fichier";
    		file_put_contents($file_output, $json_export);
    		echo " => OK";
    		@file_put_contents(URL_LOG_FILE, count($parameters)." IDs traités\r\n", FILE_APPEND);
    	}
    }
    Merci par avance.

  2. #2
    Expert confirmé
    Avatar de rawsrc
    Homme Profil pro
    Dev indep
    Inscrit en
    Mars 2004
    Messages
    6 142
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Dev indep

    Informations forums :
    Inscription : Mars 2004
    Messages : 6 142
    Billets dans le blog
    12
    Par défaut
    Salut,

    Il faudrait préciser quelle version de PHP sert à exécuter ce travail.
    Sinon clearstatcache() devrait être ton ami (une piste dans la mesure ou tu ne fais aucun profilage)

  3. #3
    Membre éclairé
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    581
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2006
    Messages : 581
    Par défaut
    Bonjour,
    C'est du PHP 5.

  4. #4
    Expert confirmé
    Avatar de rawsrc
    Homme Profil pro
    Dev indep
    Inscrit en
    Mars 2004
    Messages
    6 142
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Dev indep

    Informations forums :
    Inscription : Mars 2004
    Messages : 6 142
    Billets dans le blog
    12
    Par défaut
    Version exacte stp

  5. #5
    Membre éclairé
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    581
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2006
    Messages : 581
    Par défaut
    Php 5.3.14

  6. #6
    Expert confirmé Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    3 018
    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 : 3 018
    Par défaut
    Déjà je vois que ton code fait deux fois la même chose pour chaque fichier:
    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
    function IsJSONValid($json) {
    	$string = json_decode(file_get_contents($json), true);
    	$key = array_keys($string); // Clé dynamique en cas de changement de structure du JSON
    	if (count($string[$key[0]]) > 0) {
    		return true;
    	} else {
    		return false;
    	}
    }
    ...
    if (file_exists($file_input) && IsJSONValid($file_input)) {
        $json = file_get_contents($file_input);
        $json_content = json_decode($json, true);
        $json_key = array_keys($json_content);
    ...
    Les mêmes opérations (dont un chargement de fichier) sont faites une fois dans ta fonction IsJSONValid et une autre fois après le if.

    Tu devrais virer cette fonction IsJSONValid et faire le test sur le premier item après:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    if ( file_exists($file_input) ) {
        $json = file_get_contents($file_input);
        $json_content = json_decode($json, true);
        $json_key = array_keys($json_content);
     
        if ( count($json_content[$json_key[0]]) > 0 ) {
            foreach ($json_content[$json_key[0]] as $value) {
                // Traitements
                // $parameters[$id] = ...
            }
        }
    }
    Ça t'évite déjà 19000 chargements de fichier et 19000 décodages.

  7. #7
    Expert confirmé Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    3 018
    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 : 3 018
    Par défaut
    Autre chose, au lieu de tout engranger dans ta variable $json_export puis d'écrire le fichier résultat d'un coup, tu devrais essayer d'ouvrir le fichier $file_output avec fopen en écriture et de le remplir au fur et à mesure avec fwrite pour voir ce que ça donne. Si tes fichiers json sont de taille importante tu gagneras en mémoire.

  8. #8
    Membre éclairé
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    581
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2006
    Messages : 581
    Par défaut
    Effectivement c'est plus simple comme ça.
    J'ai retiré la fonction et je vérifie la validité directement dans la boucle, et j'ai ajouté un clearstatcache après l'export, à la fin de chaque boucle.
    On va voir ce que ça donne !

  9. #9
    Membre éclairé
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    581
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2006
    Messages : 581
    Par défaut
    Bon ça ne change rien, script lancé à 14h30, il tournait en moyenne à 0.05 sec pour traiter un cas.
    2h après et 2660 cas traités, je suis à 30 ou 40 sec pour un cas...

  10. #10
    Expert confirmé
    Avatar de rawsrc
    Homme Profil pro
    Dev indep
    Inscrit en
    Mars 2004
    Messages
    6 142
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Dev indep

    Informations forums :
    Inscription : Mars 2004
    Messages : 6 142
    Billets dans le blog
    12
    Par défaut
    Salut,

    tu n'as pas moyen de changer de version de PHP ?
    Jusqu'à la 5.4, la manip de fichiers n'était pas optimisée du tout

  11. #11
    Membre éclairé
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    581
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2006
    Messages : 581
    Par défaut
    Bientôt je vais pouvoir passer sur PHP 7, mais d'ici-là !!

  12. #12
    Modératrice
    Avatar de Celira
    Femme Profil pro
    Développeuse PHP/Java
    Inscrit en
    Avril 2007
    Messages
    8 633
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeuse PHP/Java
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2007
    Messages : 8 633
    Par défaut
    Il y a peut-être des choses qui s'accumulent en mémoire. Essaye d'ajouter un affichage de la mémoire au début de la boucle pour vérifier (memory_​get_​usage).
    Modératrice PHP
    Aucun navigateur ne propose d'extension boule-de-cristal : postez votre code et vos messages d'erreurs. (Rappel : "ça ne marche pas" n'est pas un message d'erreur)
    Cherchez un peu avant poser votre question : Cours et Tutoriels PHP - FAQ PHP - PDO une soupe et au lit !.

    Affichez votre code en couleurs : [CODE=php][/CODE] (bouton # de l'éditeur) et [C=php][/C]

  13. #13
    Membre éclairé
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    581
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2006
    Messages : 581
    Par défaut
    Oui, la mémoire utilisée augmente, et au bout d'un moment elle est saturée à 100%.
    Mais je ne comprends pas ce qui la sature.

  14. #14
    Membre très actif
    Homme Profil pro
    Déveleoppeur Web/Mobile
    Inscrit en
    Avril 2013
    Messages
    330
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Déveleoppeur Web/Mobile
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Avril 2013
    Messages : 330
    Par défaut
    19000 entrées traitées en php ne devraient pas poser de problème de lenteur. D'expérience, c'est soit un problème d'optimisation, soit une erreur générée du à l'environnement apache.
    Pour pousser le diagnostic dis nous plus précisément ce qu'il se passe : le script se termine t-il correctement au bout d'un moment ou tourne t il indéfiniment ?

    S'il tourne indéfiniment, vérifie les logs d'erreur sur ton serveur et poste les ici .

    Cdt

  15. #15
    Modératrice
    Avatar de Celira
    Femme Profil pro
    Développeuse PHP/Java
    Inscrit en
    Avril 2007
    Messages
    8 633
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeuse PHP/Java
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2007
    Messages : 8 633
    Par défaut
    Et si c'est un problème d'optimisation, il va falloir nous montrer la dernière version de ton script, histoire qu'on puisse regarder si on voit quelque chose à corriger
    Modératrice PHP
    Aucun navigateur ne propose d'extension boule-de-cristal : postez votre code et vos messages d'erreurs. (Rappel : "ça ne marche pas" n'est pas un message d'erreur)
    Cherchez un peu avant poser votre question : Cours et Tutoriels PHP - FAQ PHP - PDO une soupe et au lit !.

    Affichez votre code en couleurs : [CODE=php][/CODE] (bouton # de l'éditeur) et [C=php][/C]

Discussions similaires

  1. Windows Azure : plus simple, plus flexible, plus ouvert
    Par Gordon Fowler dans le forum Microsoft Azure
    Réponses: 2
    Dernier message: 08/06/2012, 21h44
  2. [XSLT] Faire une boucle sur une variable [i]
    Par PoT_de_NuTeLLa dans le forum XSL/XSLT/XPATH
    Réponses: 8
    Dernier message: 07/06/2010, 12h45
  3. [JDBC]Boucle sur tous les éléments du ResultSet
    Par Terminator dans le forum JDBC
    Réponses: 1
    Dernier message: 22/09/2005, 19h30
  4. L'installation d'XP boucle sur elle-même
    Par pf106 dans le forum Windows XP
    Réponses: 13
    Dernier message: 20/08/2005, 14h55
  5. [MFC] Boucle sur un bouton
    Par karl3i dans le forum MFC
    Réponses: 6
    Dernier message: 17/02/2004, 11h37

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