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 :

Optimisation scripts à longue durée d'éxécution


Sujet :

Langage PHP

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Janvier 2011
    Messages : 9
    Points : 10
    Points
    10
    Par défaut Optimisation scripts à longue durée d'éxécution
    Bonjour,

    Plusieurs questions m'amènent à demander vos avis ici:

    Imaginons que j'ai stocké ds une BD plusieurs milliers d'adresse d'image que je dois télécharger, redimensionner, modifier, puis finalement sauvegarder et uploader via des APIs.

    J'imagine que le temps d'éxécution depassera facilement les 30 voir 60 secondes de bases de "max_execution_time" .

    1) Concernant l'optimisation et la manière de faire, avez-vous un avis sur la question (sans multi-threads pour cause php) ?

    2) Même en supposant que vous m'ayez donné la meilleure réponse, je pense que le le temps d'exécution dépassera 60s... Cela peut ne pas être un problème si je modifie cette valeur ds php.ini, quoique la documentation indique :
    "Votre serveur web peut avoir d'autres configurations de la durée limite d'exécution qui peuvent également interrompre PHP. Apache a une directive Timeout et IIS a une fonction CGI pour cela. Par défaut, elles valent toutes les deux 300 secondes. Reportez-vous à la documentation de votre serveur web pour plus de détails. "
    Personnellement, j'ai testé en local sur WAMP en modifiant uniquement PHP.ini et certains script durant 20min fonctionnent parfaitement.

    Sachant que c'est pour une application en ligne, est-il possible de modifier ces paramètres sur certaines offres de "semi-dédié" ? Si oui, pouvez vous m'indiquer quels hébergeurs le proposent ? ( OVH, hosteur.com, ...)

    3) Admettons que cette action (télécharger et traiter les images) soit déclenchée par l'utilisateur, je le vois mal patienter pendant le temps de traitement. Comment faire pour laisser l'utilisateur naviguer sur le site pendant que le script continue à tourner ?
    Est-ce que l'utilisation de sleep() et de "daemons" (je ne sais pas encore ce que c'est) est une bonne piste ?
    Ou utiliser de l'ajax pour le coté asynchrone ? (permet d'appeler le script sans que la navigation soit bloquée)


    Merci d'avance pour vos réponses que j'espère précises et exhaustives

  2. #2
    Expert éminent
    Avatar de Benjamin Delespierre
    Profil pro
    Développeur Web
    Inscrit en
    Février 2010
    Messages
    3 929
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Février 2010
    Messages : 3 929
    Points : 7 762
    Points
    7 762
    Par défaut
    Hello

    A moins que tu ne veuilles faire toutes les images d'un coup ou que tes images soient en très haute résolution, on devrait rester dans des limites acceptables (de l'ordre de 30s grand max) pour la manipulation d'une image. Ce que tu cherches à faire c'est un bulk de traitement lancé par l'utilisateur c'est bien ça ?

    Il y a en effet plusieurs façons de procéder:
    - soit on place un script en crontab qui se lance à intervale régulier et qui produit un nombre fini d'image (un lot de 10 par exemple) et place les compteurs qui vont bien en BDD ou sur fichier. Cette solution suppose un contrôle complêt du serveur et donc les solutions d'hébergement mutualisés ne peuvent convenir.
    - soit on laisse l'utilisateur lancer un bulk avec Ajax de telle sorte qu'on lance 10 requêtes assynchrones qui se renouvellent dès qu'elles ont fini leur traitement (une requête permet de manipuler une et une seule image).

    Avec la deuxième solution, on fera virtuellement de la parallélisation. Apache lancera 10 thread (1 pour chaque requête assynchrone). ça peut se faire assez simplement je pense et en plus l'utilisateur peut continuer à utiliser le site tant qu'il ne change pas de page bien entendu (ou alors il faut que la nouvelle page reprenne le bulk en cours ce qui amnène pas mal de problèmes).

    Le souci se situe selon moi plus au niveau de la charge, la manipulation d'images en PHP étant par nature très lourde, il se peut que tu aies des soucis avec ton hébergeur si tu mets l'UC à 100 pendant 24h par exemple

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Janvier 2011
    Messages : 9
    Points : 10
    Points
    10
    Par défaut
    Merci pour ta réponse.
    Je suis en train de me renseigner sur les "daemons", je vais pousser un peu plus de ce côté, mais il semble que ca pourrait correspondre à ce que je cherche.
    Un exemple ici.

    Petit problème, il semblerait que l'on doive avoir un serveur dédié pour ca.

    Toute autre suggestion sera la bienvenue

  4. #4
    Expert éminent
    Avatar de Benjamin Delespierre
    Profil pro
    Développeur Web
    Inscrit en
    Février 2010
    Messages
    3 929
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Février 2010
    Messages : 3 929
    Points : 7 762
    Points
    7 762
    Par défaut
    Petit problème, il semblerait que l'on doive avoir un serveur dédié pour ca.
    Oui tout à fait. Un daemon est l'équivalent d'un service sous windows. Tu as dû remarquer que beaucoup de process portent le nom pnamed (comme httpd pour http daemon), ce sont tous des daemons.

    Ton article à l'air assez intéressant, je vais y jeter un oeil.

    -- Edit

    Dans ton cas je ne suis pas sûr qu'un Daemon soit d'une quelconque utilité. Comment comptais-tu t'en servir ? En fait quels sont les besoins de ton application au fil du temps ?

  5. #5
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Janvier 2011
    Messages : 9
    Points : 10
    Points
    10
    Par défaut
    L'intérêt serait justement de pouvoir effectuer de long traitement sans bloquer l'utilisateur.
    Dans l'exemple donné, il effectue un traitement lorsqu'il y a une nouvelle valeur dans la BD.

    Ca pourrait être le cas pour moi, imaginons qu'un vendeur ( prestashop, rue du commerce, eBay, amazon, ...) veuille changer toutes ses images de produits pour y ajouter un watermark, comment résoudre cette problèmatique ?
    Il faut bien qu'il accède à un backoffice, determine quelle image sert de watermark, et que je procède à la création et au remplacement sur le dit site.

    Le vendeur ne va pas attendre un heure sur mon site que le script se termine, donc c'est là que je pensais faire intervenir le daemon.
    L'utilisateur demande la maj, et j'estime le tps nécessaire en fonction du nombre d'annonces, pour qu'il fasse autre chose pendant ce temps.

    Reste à voir comment faire communiquer le daemon avec mon application (le principe de consulter régulièrement la la BD pourrait marcher).


    EDIT--------------------------------------------------------------------

    En comment de mon lien on peut trouver open-source Daemon platform j'y jetterai un coup d'oeil ce soir. J'espère juste ne pas m'engager dans la mauvaise direction

  6. #6
    Expert éminent
    Avatar de Benjamin Delespierre
    Profil pro
    Développeur Web
    Inscrit en
    Février 2010
    Messages
    3 929
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Février 2010
    Messages : 3 929
    Points : 7 762
    Points
    7 762
    Par défaut
    le principe de consulter régulièrement la la BD pourrait marcher
    Le pooling est très largement déconseillé dans ce cas. Il vaut mieux envoyer un signal à ton daemon pour lui dire de démarrer ou s'arrêter. Regarde les signaux posix pour mieux comprendre.

  7. #7
    Membre expert Avatar de RunCodePhp
    Profil pro
    Inscrit en
    Janvier 2010
    Messages
    2 962
    Détails du profil
    Informations personnelles :
    Localisation : Réunion

    Informations forums :
    Inscription : Janvier 2010
    Messages : 2 962
    Points : 3 947
    Points
    3 947
    Par défaut
    Salut

    Pure suggestion, donc faut voir, mais ne suffirait il pas de faire cette opération dans une autre fenêtre ?

    En gros, et pour exemple, la personne a devant elle la page de l'opération en question.
    Dès validation, on ouvre d'abord une nouvelle fenêtre (genre window.open), et on dit que l'utilisateur qu'il peu continuer à naviguer dans cette nouvelle fenêtre.
    L'autre fenêtre continu de faire ce qu'il est prévu (gros traitements), et au bout, on prend soin de faire un rechargement en disant : C'est fini.
    L'utilisateur n'est pas bloqué.
    (ou l'inverse, on ouvre une nouvelle fenêtre ou devra se dérouler l'opération, l'utilisateur peu continuer de naviguer dans la fenêtre principale).


    En tout cas, dans les divers sites où je fais ça et qu'aucune nouvelle fenêtre n'est proposée, il suffit de faire un clic droit sur un lien, puis "ouvrir dans un nouvelle fenêtre" (ou onglet), et je continu.
    Donc dans l'absolu, "forcer" d'ouvrir une nouvelle fenêtre n'est pas nécessaire.
    Disons qu'on le fait pour les utilisateurs non avertis.


    Cependant, le problème du temps d'exécution reste entier, et il le restera de toute manière, normal, c'est un problème serveur.
    Il te faut une formule d'hébergement adaptée, c'est certain.
    Après, on peu toujours agrémenter le système d'upload grâce à de l'ajax pour par exemple faire une barre de progression pour que l'utilisateur ne soit pas trop dans le flou.
    Après, je n'ai pas du tout de connaissances suffisante pour optimiser ce genre d'opérations coté serveur.


    Cependant, les fenêtres multiples peuvent provoquer des problèmes, et je pense particulièrement à la session.
    D'ailleurs, et vu que les traitements sont longs, et s'il y a une gestion des sessions, il faudrait à mon sens prendre soin de régulièrement reconduire la session, car admettons que la personne ne navigue plus, la session risque d'être expirée avant que l'opération ne se termine. Ca peu être un problème.
    Win XP | WampServer 2.2d | Apache 2.2.21 | Php 5.3.10 | MySQL 5.5.20
    Si debugger, c'est supprimer des bugs, alors programmer ne peut être que les ajouter [Edsger Dijkstra]

  8. #8
    Expert confirmé
    Avatar de Thes32
    Homme Profil pro
    Développeur PHP, .Net, T-SQL
    Inscrit en
    Décembre 2006
    Messages
    2 379
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations professionnelles :
    Activité : Développeur PHP, .Net, T-SQL

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 379
    Points : 4 853
    Points
    4 853
    Par défaut
    Tu pourrais faire ces opérations à l'appel du fichier. Je te l'explique en exemple, dans un premier temps ton script ne devrait pas se préoccuper de la sauvegarde mais juste stocker les fichiers tel qu'ils sont, ce n'est qu'à un appel particulier que le script vérifieras la présence du fichier de la version traitée si elle existe le client est servi sinon la crée à la volée.

    Est-ce clair ?
    Développeur | Zend Certified Engineer

    Étapes Pour mieux se servir du forum:
    1. Commencez par lire les cours et tutoriels ;
    2. Faites une recherche;
    3. Faites un post si rien trouvé dans les deux étapes précédentes en respectant les règles;

    Nix>_Rien n'est plus pratique que la théorie

  9. #9
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Janvier 2011
    Messages : 9
    Points : 10
    Points
    10
    Par défaut
    Citation Envoyé par Thes32 Voir le message
    Tu pourrais faire ces opérations à l'appel du fichier. Je te l'explique en exemple, dans un premier temps ton script ne devrait pas se préoccuper de la sauvegarde mais juste stocker les fichiers tel qu'ils sont, ce n'est qu'à un appel particulier que le script vérifieras la présence du fichier de la version traitée si elle existe le client est servi sinon la crée à la volée.

    Est-ce clair ?
    Euh... pas vraiment.
    Ce dont j'ai besoin, c'est de télécharger, modifier, sauvegarder (puis uploader via des APIs) des milliers de photos, et ce quand l'utilisateur le demande ( c'est possible une seule fois seulement par utilisateur).

    Pourrais tu détailler un peu plus stp ?

  10. #10
    Expert éminent
    Avatar de Benjamin Delespierre
    Profil pro
    Développeur Web
    Inscrit en
    Février 2010
    Messages
    3 929
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Février 2010
    Messages : 3 929
    Points : 7 762
    Points
    7 762
    Par défaut
    C'est simple, Thes32 te propose une solution pour servir les fichiers "à la demande". Si sur un jeu de 1000 fichiers, seulement 100 ne sont qu'effectivement utilisés, les 900 autres auront été traités en pure perte.
    La solution consiste donc à ne faire les traitements que lors qu'un utilisateur à besoin d'une ressource (comme par exemple un utilisateur du site télécharge une image sur son navigateur).
    C'est à toi de nous dire si, en fonction des besoins de ton application, c'est jouable ou pas.
    Si l'objectif est comme je le pense de traiter des images en mode batch, effectivement ce n'est pas la bonne solution et on pourra être amené à se pencher sur les cron ou les daemons.

  11. #11
    Expert éminent
    Avatar de Benjamin Delespierre
    Profil pro
    Développeur Web
    Inscrit en
    Février 2010
    Messages
    3 929
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Février 2010
    Messages : 3 929
    Points : 7 762
    Points
    7 762
    Par défaut
    En repenssant à ta solution de deamon que tu évoques plus haut, j'aurais bien une idée pour mettre tout ça sur pied.

    On créé un daemon qui, une fois démaré se mets en attente d'un signal sur la plateforme (il vaut toujours mieux un signal ou un webservice qu'un pooling en base de données).
    A la récéption du signal, le daemon va créer un fork - exactement comme le fait le httpd: à chaque requête son thread. Ce fork va alors se charger d'effectuer le bulk en "arrière plan" vis-a-vis de ton service PHP et va mettre à jour un journal et des compteurs en base de données ou sur fichier (il faudra optimiser le processus en ce sens pour que la journalisation ne soit pas un frein à notre daemon).
    Coté Web, on va fournir au client une interface pour démarer, arrêter et reprendre le bulk (toujours en envoyant des signaux à notre daemon) et on pourra sur chaque page afficher un status du (des) bulk(s) en cours sans gêner la navigation.
    Une fois le bulk terminé, lors de l'affichage d'une page, PHP devra montrer au client le status final et eventuellement lui proposer de consulter le journal.

    On peut également mettre par dessus du JavaScipt pour dynamiser tout ça et améliorer l'expérience utilisateur mais c'est facultatif.

    Les technologies que je te recommande pour mener ce projet à bien:
    - PHP 5.3 pour son optimisation mémoire et son garbage collector, indispensable dans le cas d'un daemon pour éviter les fuites mémoires
    - extention pcntl pour les forks et les signaux (doc ici http://php.net/manual/en/book.pcntl.php)
    - MySQL 5, requêtes préparées, procédures, triggers et partitionnement de tables sont au menu
    - JavaScipt, Ajax et jQuery pour donner du dynamisme à tout ça (en option)

    Je te recommande de bien te documenter sur PHP en mode CLI, car les différences avec le fonctionnement web classique sont nombreuses.
    Je te recommande l'usage de MySQL Workbench pour le design et la mise à jour de la base de données
    Je te recommande de lire le manuel de sta sous Unix pour monitorer à intervalles régulier la charge de la plateforme.

  12. #12
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Janvier 2011
    Messages : 9
    Points : 10
    Points
    10
    Par défaut
    Merci beaucoup pour t'être penché sur mon problème

    Il me semble que la solution que tu proposes corresponde à ma problématique.
    Je vais donc suivre tes conseils, et essayer de coder quelque chose dans ce sens.
    Etant donné le nombre de concepts à apprendre pour moi (PHP en mode CLI, extention pcntl , MySQL Workbench ...) je vais surement mettre un peu de temps.
    Une fois un version "basique créée" je posterai pour qu'on puisse voir comment l'améliorer.

    En attendant si tu trouves (ou un visiteur) une solution plus simple (si ca existe...) je suis toujours preneur

  13. #13
    Expert éminent
    Avatar de Benjamin Delespierre
    Profil pro
    Développeur Web
    Inscrit en
    Février 2010
    Messages
    3 929
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Février 2010
    Messages : 3 929
    Points : 7 762
    Points
    7 762
    Par défaut
    la solution la plus simple dans ton cas consiste à jouer au Goret: mettre un temps d'éxécution pas croyable et faire tourner le bulk de manière synchrone avec la demande du client

  14. #14
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Janvier 2011
    Messages : 9
    Points : 10
    Points
    10
    Par défaut
    Bon finalement je fais le "goret", max_execution_time à 1200 (valeur de test) et puis un petit coup d'ajax.

    Voila mon code de test, j'essaierai demain en situtation réel sur mon serv en local pour 1000 photos.

    ma page testajax.html (certaines lignes sont inutiles, c'est un crt-c/ctrl-v d'un viieux test) :

    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
    <html>
    <head>
    </head>
    <body>
     
    <a id="lien" href="#">Lancer le script</a>
     
     
    <div id="ici">
    </div>
     
    <script type="text/javascript" src="prototype.js"></script>
    <script type="text/javascript">
     
    Event.observe(window, 'load', function() {
     Event.observe($('lien'), 'click', function(event) {
     new Ajax.Updater(
     
    'ici',
    'wait.php',
     { 
     insertion: Insertion.Top,
     frequency: 6,
     decay: 1
     }
     );
     //$('lien').parentNode.removeChild($('lien'));
     //Event.stop(event);
    }.bindAsEventListener())
     }); 
    </script>
     
    <a href="http://www.harald.fr" > je vais ici </a>
    </body>
    </html>
    mon script wait.php :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    <?php
     
    $timeOnLaunch = date("H:i:s");
    $waitTime = 50;
     
    sleep( $waitTime );
    $timeOnEnd = date("H:i:s");
    $f = fopen( "test_".$waitTime.".txt", "w+");
    $data = " date de lancement du script : ".$timeOnLaunch ." | date de création du fichier: ".$timeOnEnd." | attente: ".$waitTime;
    fwrite( $f, $data );
    fclose( $f );
    ?>
    Le résultat :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
      date de lancement du script : 17:15:45 | date de création du fichier: 17:16:35 | attente: 50

Discussions similaires

  1. Pages ASP qui se figent à cause d'un script de longue durée ?
    Par Franck.H dans le forum Visual Studio
    Réponses: 2
    Dernier message: 20/08/2014, 15h59
  2. [PHP 5.3] Script longue durée et gestion en file d'attente
    Par sbadecoder dans le forum Langage
    Réponses: 7
    Dernier message: 25/02/2014, 20h28
  3. Réponses: 2
    Dernier message: 20/02/2008, 11h16
  4. Optimisation script pour réordonner des N° de Lots
    Par polemoss dans le forum MySQL
    Réponses: 1
    Dernier message: 06/06/2007, 18h37
  5. Gettickcount longue durée
    Par BECHE dans le forum Langage
    Réponses: 3
    Dernier message: 06/12/2005, 23h01

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