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 code PHP


Sujet :

Langage PHP

  1. #1
    Membre régulier Avatar de la_chouette
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    183
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 183
    Points : 121
    Points
    121
    Par défaut Optimisation code PHP
    Bonjour,

    Le code PHP ci-dessous permet de parser puis d’afficher et paginé le contenu d’un fichier texte contenant plus de 830 000 lignes.

    Le problème est qu’il utilise plus de mémoire qu’il n'ait allouée à PHP, c’est-à-dire 128mo.

    Avez-vous des recommandations sur l’optimisation du code PHP pour baisser la consommation de mémoire lors de son exécution ?

    Merci de votre aide.

    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
    <?php
    $lines = file_get_contents('file.txt');
     
    $perpage = 5; //Number of lines per page
     
    $searchString = $_GET['search']; //Insert word(s) you're searching for
    $pattern = preg_quote($searchString, '/');
    $pattern = "/^.*$pattern.*/mi";
     
    if(preg_match_all($pattern, $lines, $matches)){
        $line_amount = count($matches[0]);
    } else {
        echo "No matches found";
    }
     
    $p = isset($_GET['page']) ? $_GET['page'] : 1;
    for ($i = (($p * $perpage) - $perpage); $i <= (($perpage * $p) - 1); $i++){
        if($i >= $line_amount){
            break;
        } else {
            echo $matches[0][$i].'<br />';
        }
    }
    ?>
     
    <table summary="" cellpadding="10" cellspacing="0"  border="0">
        <tr>
    	<?php
    	$link = "";
    	$page = $_GET['page']; // your current page
    	$pages=$line_amount/$perpage; // Total number of pages
     
    	$perpage=5  ; // May be what you are looking for
     
        if ($pages >=1 && $page <= $pages)
        {
            $counter = 1;
            $link = "";
            if ($page > ($perpage/2))
    			$link .= "<td><a href=\"?page=1\">1 </a></td> <td>...</td> ";
     
            for ($x=$page; $x<=$pages;$x++)
            {
                if($counter < $perpage)
                    $link .= "<td><a href=\"?page=" .$x."\">".$x." </a></td>";
     
                $counter++;
            }
            if ($page < $pages - ($perpage/2))
    				$link .= "<td>...</td> " . "<td><a href=\"?page=" .$pages."\">".$pages." </a></td>";
        }
     
        echo $link;
    	?>
    	</tr>
    </table>
    La vitesse de la lumière étant supérieure à celle du son, beaucoup de gens sont brillants jusqu'à ce qu'ils ouvrent leur bouche.

  2. #2
    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 : 39
    Localisation : France

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

    Informations forums :
    Inscription : Avril 2007
    Messages : 8 633
    Points : 16 372
    Points
    16 372
    Par défaut
    Le principal problème de ton script est qu'il lit la totalité du fichier, qu'il passe la regex sur la totalité des lignes et ensuite seulement il filtre les résultats de la pagination.

    Un axe d'optimisation serait de découper la lecture du fichier en plusieurs parties, par exemple par bloc de 1000 lignes, histoire de ne pas avoir la totalité du fichier en mémoire. Tu lis, tu parses, tu conserves uniquement les lignes qui t'intéressent et tu recommences jusqu'à la fin du fichier.
    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]

  3. #3
    Membre régulier Avatar de la_chouette
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    183
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 183
    Points : 121
    Points
    121
    Par défaut
    Bonjour celira,

    effectivement, j'applique ton conseil tout de suite.

    Merci
    La vitesse de la lumière étant supérieure à celle du son, beaucoup de gens sont brillants jusqu'à ce qu'ils ouvrent leur bouche.

  4. #4
    Modérateur

    Avatar de MaitrePylos
    Homme Profil pro
    DBA
    Inscrit en
    Juin 2005
    Messages
    5 496
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : Belgique

    Informations professionnelles :
    Activité : DBA
    Secteur : Service public

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 496
    Points : 12 596
    Points
    12 596
    Par défaut
    Pas sur que cela dégrossise mais essaye déjà ça

    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
     
    <?php
     
    $lines = file_get_contents('file.txt');
     
    $perpage = 5; //Number of lines per page
     
    $searchString = $_GET['search']; //Insert word(s) you're searching for
    $pattern = preg_quote($searchString, '/');
    $pattern = "/^.*$pattern.*/mi";
     
    if (preg_match_all($pattern, $lines, $matches)) {
        $line_amount = count($matches[0]);
    } else {
        echo "No matches found";
    }
     
    //$p = isset($_GET['page']) ? $_GET['page'] : 1;
     
    $p = 1;
    if($_GET['page'])
    {
        $p = $_GET['page'];
    }
     
    $i_perpage = ($p*$perpage- - $perpage;
    $i_lte_perpage = ($perpage * $p) - 1;
     
    for ($i = $i_perpage; $i <= $i_lte_perpage; $i++) {
        if ($i >= $line_amount) {
            break;
        } else {
            echo $matches[0][$i] . '<br />';
        }
    }
    ?>
     
    <table summary="" cellpadding="10" cellspacing="0" border="0">
        <tr>
            <?php
            $link = "";
            $page = $_GET['page']; // your current page
            $pages = $line_amount / $perpage; // Total number of pages
     
            $perpage = 5; // May be what you are looking for
     
            if ($pages >= 1 && $page <= $pages) {
                $counter = 1;
                $link = "";
                if ($page > ($perpage / 2))
                    $link .= "<td><a href=\"?page=1\">1 </a></td> <td>...</td> ";
     
                for ($x = $page; $x <= $pages; $x++) {
                    if ($counter < $perpage)
                        $link .= "<td><a href=\"?page=" . $x . "\">" . $x . " </a></td>";
     
                    $counter++;
                }
                if ($page < $pages - ($perpage / 2))
                    $link .= "<td>...</td> " . "<td><a href=\"?page=" . $pages . "\">" . $pages . " </a></td>";
            }
     
            echo $link;
            ?>
        </tr>
    </table>

  5. #5
    Membre régulier Avatar de la_chouette
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    183
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 183
    Points : 121
    Points
    121
    Par défaut
    Bonjour MaitrePylos,

    Merci de ton aide.

    Le code PHP utilise toujours trop de mémoire, je pense que je dois d’abord limiter le nombre de données lue/chargée en mémoire comme préconiser par celira et ensuite optimisé le traitement.
    La vitesse de la lumière étant supérieure à celle du son, beaucoup de gens sont brillants jusqu'à ce qu'ils ouvrent leur bouche.

  6. #6
    Expert éminent Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 858
    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 858
    Points : 6 556
    Points
    6 556
    Par défaut
    Oui, je suis d'accord avec Celira. D'ailleurs tu n'as pas besoin d'une regex (qui ne recherche qu'une sous-chaîne litérale). Si tu travailles ligne par ligne avec:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    $fh = fopen("file.txt", "r");
    if ($fh) {
        while (($line = fgets($fh)) !== false) {
            ...
    Il te suffit d'utiliser la fonction stripos pour savoir si la ligne contient le motif de recherche (donc plus besoin de preg_quote non plus), ça n'en sera que plus rapide.
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

  7. #7
    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
    En version SPL :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    $file = new SplFileObject("fichier.txt");
    $results = array();
    while (!$file->eof()) {
        $line = $file->fgets();
        if(strripos($line,$recherche) !== false) {
            $results[] = $line;
        }
    }
    https://secure.php.net/manual/fr/cla...fileobject.php

    L'avantage c'est que tu peux sauter directement à une ligne donnée si tu sais ou aller et donc ne pas tout lire.
    Tu pourrais donc imaginer la construction d'un index pour accélérer les accès à ton fichier si il sont récurrents.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    $file = new SplFileObject("fichier.txt");
    $file->seek(1234); //Saut à la ligne 1234
    echo $file->current(); // Affiche la ligne
    Dans tous les cas il faut si possible éviter les regex sur des traitements aussi lourd.
    Pry Framework php5 | N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  8. #8
    Membre régulier Avatar de la_chouette
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    183
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 183
    Points : 121
    Points
    121
    Par défaut
    Merci pour conseils CosmoKnacki et grunk.

    En faites je ne saisi pas comment traiter le fichier ligne par ligne (comme vous me conseiller) en affichant 100 résultats par page tout en gérant la pagination.

    Je suis forcement obliger de stocker en mémoire le volume de données renvoyer (sur un fichier de 830 000 lignes minimum, je peux avoir 300 000 lignes de résultat pour une recherche que je dois afficher via une pagination).

    En googlisant, je viens de tomber sur une petite astuce concernant la mémoire utiliser par php : http://www.bigeng.io/php-memory-optimization/
    La vitesse de la lumière étant supérieure à celle du son, beaucoup de gens sont brillants jusqu'à ce qu'ils ouvrent leur bouche.

  9. #9
    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 : 39
    Localisation : France

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

    Informations forums :
    Inscription : Avril 2007
    Messages : 8 633
    Points : 16 372
    Points
    16 372
    Par défaut
    Pour la partie pagination, on pourrait imaginer passer par un fichier temporaire intermédiaire : tu lis le fichier principal ligne à ligne; si la ligne correspond, tu l'écris dans le fichier temporaire. Et ensuite, pour la pagination, tu as "juste" à la lire les lignes n à n+5.
    L'avantage , c'est qu'en plus de libérer de la mémoire, le fichier temporaire peut servir de cache : tant que la chaine recherchée et le fichier source ne changent pas, il est inutile de reparser le fichier source : tu peux lire directement le fichier temporaire.
    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]

  10. #10
    Expert éminent Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 858
    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 858
    Points : 6 556
    Points
    6 556
    Par défaut
    En fait, la seule chose que tu dois stocker c'est les numéros de ligne après un premier parsage ligne par ligne du fichier (tu dois le stocker quelque part pour ne plus avoir à le refaire).
    Ensuite, tu déduis par le calcul le numéro de la première ligne de la page où se trouve la ligne avec la correspondance que tu veux afficher, puis en utilisant la méthode SplFileObject::fseek, tu places le pointeur sur cette ligne, puis tu lis les x lignes de la page.

    Pour le calcul: ligne_correspondance - ligne_correspondance%nb_lignes_par_page ( % représente le modulo).

    Donc tout ce qui occupe la mémoire c'est la page courante.
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

  11. #11
    Membre régulier Avatar de la_chouette
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    183
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 183
    Points : 121
    Points
    121
    Par défaut
    Merci Celira et CosmoKnacki, j'applique vos conseils.
    La vitesse de la lumière étant supérieure à celle du son, beaucoup de gens sont brillants jusqu'à ce qu'ils ouvrent leur bouche.

  12. #12
    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
    Ceci étant dit , ne serait ce pas judicieux detransformer ton fichier en une base de données qui est dédié à ce genre d'usage ?
    Pry Framework php5 | N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  13. #13
    Expert éminent Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 858
    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 858
    Points : 6 556
    Points
    6 556
    Par défaut
    Pas faux.
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

Discussions similaires

  1. [MySQL] Optimisation de Code Php Jquery
    Par PainkillerDev dans le forum PHP & Base de données
    Réponses: 0
    Dernier message: 09/07/2013, 17h18
  2. Optimisation de code php
    Par Oprichnik dans le forum Humour Informatique
    Réponses: 2
    Dernier message: 16/04/2011, 20h53
  3. Optimisation du code PHP vs SQL
    Par persia dans le forum PHP & Base de données
    Réponses: 10
    Dernier message: 18/11/2010, 20h10
  4. Optimisation de code PHP
    Par MeHo_ dans le forum Langage
    Réponses: 9
    Dernier message: 29/04/2009, 11h21
  5. Question optimisation de code PHP/HTML
    Par heavenvibes dans le forum Langage
    Réponses: 7
    Dernier message: 14/08/2008, 11h57

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