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 :

Exploiter au maximun les ressources du serveur sans erreur fatal. (max_execution_time, memory_limit)


Sujet :

Langage PHP

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Inscrit en
    Janvier 2012
    Messages
    97
    Détails du profil
    Informations forums :
    Inscription : Janvier 2012
    Messages : 97
    Par défaut Exploiter au maximun les ressources du serveur sans erreur fatal. (max_execution_time, memory_limit)
    Bonjour à tous.

    Je doit développer une page qui va afficher le maximun de ligne issue de ma base.

    J'ai donc développé cette petite classe afin que mon programme puisse exploiter le plus de ressource possible sans atteindre la limite critique et fatal de la memory_limit ou du max_execution_time.

    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
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    <?php
    /**
     * 
     * @author moi
     * 
     * <code lang="php">
     * ini_set('max_execution_time', 1200); # On se donne plus de temps !
     * ini_set('memory_limit', '2048M'); # et de mémoire !
     * OnTheRazorsEdge::sharp();
     * while(true) {
     *     // des truc
     *     if ( ! OnTheRazorsEdge::run() ) {
     *         break;
     *     }
     * }
     * </code>
     *
     */
    class OnTheRazorsEdge
    {
        const STOP_T_RETURN = false;
        const STOP_M_RETURN = false;
     
        private static $STOP_T = null;
        private static $STOP_M = null;
     
        /**
         * Affutage
         * 
         * @var float
         */
        private static $sharpening = null;
     
        public static $stopt_t_string = 'Le temp d\'excécution actuel (%1$d) et suppérieur au temps d\'exécution aloué (%2$d). Il est temps de s\arréter.';
        public static $stopt_m_string = 'La mémoire actuellement utilisée (%1$d) et suppérieur a la mémoire aloué (%2$d). Il est temps de s\arréter.';
     
        /**
         * Aiguiser la lame du rasoir !
         * 
         * <code lang="php">
         * ini_set('max_execution_time', 60); # On se donne plus de temps !
         * ini_set('memory_limit', '2048M'); # et de mémoire !
         * OnTheRazorsEdge::sharp();
         * </code>
         * 
         * @param float $edge 
         */
        public static function sharp($sharpening = 0.8)
        {
            self::$sharpening = $sharpening;
     
            $REQUEST_TIME = $_SERVER["REQUEST_TIME"]; # Date de début du script (Aproximatif.)
            $max_execution_time = ini_get('max_execution_time'); # Durée maximal de vie du script avant plantage
            self::$STOP_T = $REQUEST_TIME + ($max_execution_time * self::$sharpening); # Si on dépace 80% du temps max on arrète proprement avant le plantage.
     
     
            $memory_limit = ini_get('memory_limit'); # ('124M')
            $memory_limit_octet = ((int)$memory_limit)*1024*1024;
            self::$STOP_M = $memory_limit_octet * self::$sharpening; # Si on dépace 80% de la mémoire max on arrète proprement avant le plantage.
        }
     
        /**
         * Courir sur la lame du rasoir !
         * 
         * @return boolean true si on peut continuer. 
         */
        public static function run()
        {
            if ( ! self::$sharpening) {
                self::sharp();
            }
     
            $T = microtime(true);
            if ($T > self::$STOP_T) {
                $msg = sprintf(self::$stopt_t_string, $T, self::$STOP_T);
                return self::STOP_T_RETURN;
            }
     
            $M1 = (int)memory_get_usage(true);
            $M2 = (int)memory_get_usage(false);
            $M = min($M1, $M2); 
            if ($M > self::$STOP_M) {
                $msg = sprintf(self::$stopt_m_string, $M, self::$STOP_M);
                return self::STOP_M_RETURN;
            }
            return true;
        }
    }
    La classe s'utilise comme ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    ini_set('max_execution_time', 1200); # On se donne plus de temps !
    ini_set('memory_limit', '2048M'); # et de mémoire !
    OnTheRazorsEdge::sharp();
    while(true) {
        // des truc
        if ( ! OnTheRazorsEdge::run() ) {
            break;
        }
    }
    Si je vous parle de ça c'est que je n'arrive pas à utiliser les fonctions sur la mémoire comme je veux...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    ini_set('memory_limit', '2048M'); # et de mémoire !
    $memory_limit = ini_get('memory_limit'); # '124M'
    Mon instruction 'ini_set()' ne semble pas être prise en compte.

    Cependant, sur mon environnement de dev j'arrive à exporter plus 5000 lignes.
    Alors que sur la prod le système bloque au alentour de 71, (Ce qui est complètement ridicule !)

    J'ai peut être un problème avec la fonction memory_get_usage()...

    Voila, Mon objectif et d'améliorer cette classe (la rendre viable et utile) et de la partager ^^ .


    Environnement :
    • LAMP
    • PHP 5.3.3-7+squeeze14 with Suhosin-Patch
    • eZPublish4 ezpublish-2012.6

  2. #2
    Expert confirmé Avatar de papajoker
    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2013
    Messages
    2 324
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nièvre (Bourgogne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2013
    Messages : 2 324
    Par défaut
    Boujour,
    pourquoi ne pas nous montrer la boucle DB fetch() ?

    Quel rapport avec la mémoire resortir une ligne ou 10 000 consomme la même chose !

    Vous vous assignez de la ram sur un serveur mutu c'est la classe

  3. #3
    Membre confirmé
    Inscrit en
    Janvier 2012
    Messages
    97
    Détails du profil
    Informations forums :
    Inscription : Janvier 2012
    Messages : 97
    Par défaut Mon code
    Malheureusement je ne fait pas directement ma requête sur une base de donnée. Mais sur Solr (Lucenne) par eZFind pour récupéré des eZContentObjectTreeNode issue de la base....

    Voici un extrait de mon code.

    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
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    <?php
    $http = eZHTTPTool::instance();
     
    ## Récupération des paramètres
    $enfants = $http->getVariable('enfants', null);
     
    ## Système anti plantage. 
    gc_enable(); // Enable Garbage Collector
    ini_set('max_execution_time', 1200); # On se donne plus de temps !
    ini_set('memory_limit', '2048M'); # et de mémoire !
    OnTheRazorsEdge::sharp();
     
    $LIMIT = 100; # On va fetch petit lot par petit lot. Ce serait bète de planter pandant le fetch !
    $OFFSET = 0;  # A la fin de chaque do on incrément $OFFSET de $LIMIT
     
    $filename = "export-recherche.".(ENV != ENV_PREPROD ? ENV.'.' : '').date('Y-m-d_H-i-s').'.csv';
    $file_path = eZSys::varDirectory().'/storage/export-pro/'.$filename;
    CSV::sendCsvHeaders($filename); # Envoie des entête csv
     
    # Ouverture du flux de sortie.
    # Pour économiser de ressources on ne stoque pas le csv sans un string. On l'envoie directement sur la sortie std.
    $fp = fopen('php://output', 'w'); # On ouvre directement le flux sur la sortie standard.
    if ($fp === false) {
        throw new Exception("Impossible d'ouvrir le fichier '$file_path'.");
    }
     
        $heads = array('', 'nom', 'prenom', 'naissance',
        'responsable_nom', 'responsable_prenom', 'adresse_responsable', 'complement_adresse_responsable', 
        'code_postal_responsable', 'commune_responsable', 'telephone_responsable', 'debut', 'fin'=>'fin',
        );
     
        fputcsv($fp, $heads, ';');
     
        $matrice = CSV::matrice($heads);
     
        do {
            $search_result = eZProFunctionCollection::fetchEnfants_a($enfants, $OFFSET, $LIMIT);
     
            foreach ($search_result["result"]['list'] as $i => $node) {
                $dm = $node->object()->dataMap();
                $node->object()->resetDataMap();
     
                $fields = $matrice;
                $fields['nom'] = $dm['nom']->toString();
                $fields['prenom'] = $dm['prenom']->toString();
                $fields['debut'] = $dm['date_debut_accueil']->toString() ? date('d/m/Y',$dm['date_debut_accueil']->toString()) : '';
                $fields['responsable_prenom'] = $dm['prenom_responsable']->toString();
                $fields['responsable_nom'] = $dm['nom_responsable']->toString();
                $fields['adresse_responsable'] = $dm['adresse_responsable']->toString();
                $fields['code_postal_responsable'] = $dm['code_postal_responsable']->toString();
                $fields['commune_responsable'] = $dm['commune_responsable']->toString();
                $fields['telephone_responsable'] = $dm['telephone_responsable']->toString();
     
                $communeAttContent = $dm['commune']->content();
                foreach ($communeAttContent["relation_list"] as $relation) {
                    $d = ExportMemoryCache::commune_data($relation['contentobject_id']);
                    $fields['commune'] = $d['commune'];
                    break;
                }
                unset($communeAttContent);
     
                fputcsv($fp, $fields, ';');
     
                unset($node);unset($dm); # And more !
     
                if (!OnTheRazorsEdge::run()) {
                    fputcsv($fp, array("Et plus"), ';');
                    break (2); # On break le foreach et le do while
                }
            }
     
            eZContentObject::clearCache(); # Clear in-memory caches.
            gc_collect_cycles();
     
            $OFFSET += $LIMIT;
        } while ($search_result["result"]['list']);
     
    fclose($fp);
    return eZExecution::cleanExit();
     
    class ExportMemoryCache 
    {
        private static $commune_data = array();
        public static function commune_data($commune_contentobject_id) 
        {
            if ( ! isset(self::$commune_data[$commune_contentobject_id])) {
                $fields = array('commune' => '', 'canton' => '', 'circonscription' => '');
                $communeObject = eZContentObject::fetch($commune_contentobject_id);
                if ($communeObject->ClassIdentifier == 'commune') {
                    $cdm = $communeObject->dataMap();
                    $communeObject->resetDataMap();
                    $fields['commune'] = $cdm['commune']->toString();
                    $fields['canton'] = $cdm['canton']->toString();
                    $fields['circonscription'] = $cdm['circonscription']->toString();
                    unset($cdm);
                }
                unset($communeObject);
                self::$commune_data[$commune_contentobject_id] = $fields;
            }
            return self::$commune_data[$commune_contentobject_id];
        }
    }

Discussions similaires

  1. Réponses: 7
    Dernier message: 05/09/2011, 18h10
  2. Comment Facebook, Google... gèrent t'ils les ressources et données de leurs serveurs
    Par identifiant_bidon dans le forum Général Conception Web
    Réponses: 1
    Dernier message: 07/07/2011, 16h57
  3. Migrer Samba sur un autre serveur sans perdre les machines
    Par max-mag dans le forum Administration système
    Réponses: 10
    Dernier message: 12/05/2009, 09h57
  4. Réponses: 2
    Dernier message: 18/05/2007, 11h51
  5. Réponses: 2
    Dernier message: 28/05/2006, 11h34

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