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 :

Maximum execution time


Sujet :

Langage PHP

  1. #1
    Membre du Club
    Inscrit en
    Juillet 2009
    Messages
    201
    Détails du profil
    Informations forums :
    Inscription : Juillet 2009
    Messages : 201
    Points : 48
    Points
    48
    Par défaut Maximum execution time
    Bonjour,

    J'ai un script qui permet de faire de la copie récurissive de fichiers/dossiers

    Le problème est que quand les dossiers sont trop "rempli" j'obtiens le message d'erreur :

    stderr: PHP Fatal error: Maximum execution time of 30 seconds exceeded in
    Quel est selon vous la valeur recommandé pour max_execution_time

    Merci

  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
    ça dépends. Si tu es confiant dans la capacité de ton script à faire son boulot sans planter, tu peux mettre 0. Si tu sais que de toute façon ça ne dépassera jamais X secondes, mets X tout simplement.

    Note: tu peux définir le max_execution_time au runtime avec set_time_limit.

    Et pour répondre explicitement à la question, 30 secondes c'est recommandé dans la plupart des cas (personnellement, je n'ai jamais conçu d'algorithme qui le dépasse).

  3. #3
    Inactif  
    Inscrit en
    Septembre 2011
    Messages
    100
    Détails du profil
    Informations forums :
    Inscription : Septembre 2011
    Messages : 100
    Points : 122
    Points
    122
    Par défaut
    Tu peux également réinitialisée cette durée à chaque passage de la boucle.

  4. #4
    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
    Je plussoie la valeur des 30 secondes. Si une page web met plus de 30 secondes à s'afficher, en règle générale, l'utilisateur va pas comprendre et réactualiser

    Maintenant, tu peux dépasser cette valeur dans certains cas, par exemple : un script batch lancé par une tâche périodique, un export de données particulièrement fourni, ce genre de choses.
    Par contre, si c'est une page web, il faut penser à au moins mettre un message du genre "ce traitement peut mettre quelques minutes à s'exécuter"...
    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]

  5. #5
    Membre du Club
    Inscrit en
    Juillet 2009
    Messages
    201
    Détails du profil
    Informations forums :
    Inscription : Juillet 2009
    Messages : 201
    Points : 48
    Points
    48
    Par défaut
    Bonjour merci pour vos réponses

    @Celira
    Si une page web met plus de 30 secondes à s'afficher, en règle générale, l'utilisateur va pas comprendre et réactualiser
    Non je pense pas... J'utilise JQuery/Ajax pour lancer ma fonction de copie récurssive. EN fait temps que la copie n'est pas terminée, un message apparait.

    Là, mon problème c'est que la copie est trop longue donc timeout du script php !

    @Jean-Georges
    Tu peux également réinitialisée cette durée à chaque passage de la boucle.
    Oui cela est une idée, mais comment faire pour modifier le timer ?

  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
    Tiens comme je l'ai dans mon presse-papier, voici un algo tout bête pour déplacer des fichiers:
    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
    function copy_dir ($from, $to, $reccursive = true, array & $files = null) {
        if (!is_dir($from) || !is_readable($from))
            throw new InvalidArgumentException("First parameter is not a valid directory or is not readable");
     
        if (!is_dir($to) || !is_writable($to))
            throw new InvalidArgumentException("Second parameter is not a vadlid directory or is not writeable");
     
        $from = realpath($from);
        $to   = realpath($to);
     
        if ($reccursive) {
            $dir = new RecursiveDirectoryIterator($from);
            $dir = new RecursiveIteratorIterator($dir);
        }
        else {
            $dir = new DirectoryIterator($from);
        }
     
        $files = array();
        foreach ($dir as $item) {
            $dirname          = realpath($item->getPath());
            $filename         = realpath($item->getPathname());
            $new_dirname      = str_replace($from, $to, $dirname);
            $new_filename     = str_replace($from, $to, $filename);
     
            if (!$reccursive && $item->isDir())
                continue;
            elseif(!isset($files[$new_dirname]) && !is_dir($new_dirname))
                $files[$new_dirname] = mkdir($new_dirname);
     
            $files[$new_filename] = copy($filename, $new_filename);
        }
     
        return !in_array(false, $files, true);
    }
    Mais c'est vrai que ça prends du temps.

  7. #7
    Membre habitué
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    247
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Janvier 2011
    Messages : 247
    Points : 163
    Points
    163
    Par défaut
    Pour modifier le timer:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    ini_set ('max_execution_time', 0);

  8. #8
    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
    Citation Envoyé par Benjamin Delespierre Voir le message
    Note: tu peux définir le max_execution_time au runtime avec set_time_limit.
    Bon, ini_set fonctionne aussi mais il vaut mieux utiliser les fonctions pré-définies

  9. #9
    Membre du Club
    Inscrit en
    Juillet 2009
    Messages
    201
    Détails du profil
    Informations forums :
    Inscription : Juillet 2009
    Messages : 201
    Points : 48
    Points
    48
    Par défaut
    Bonjour,

    Voici le code que j'utilise pour la copie récurssive, quand pensez-vous :

    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
     
    function copy_directory($source,$destination ) {
    	if ( is_dir( $source ) ) {
    		@mkdir( $destination );
    		$directory = dir( $source );
    		while ( FALSE !== ( $readdirectory = $directory->read() ) ) {
    			if ( $readdirectory == '.' || $readdirectory == '..' ) {
    				continue;
    			}
    			$PathDir = $source . '/' . $readdirectory;
    			if ( is_dir( $PathDir ) ) {
    				copy_directory( $PathDir, $destination . '/' . $readdirectory );
    				continue;
    			}
    			copy( $PathDir, $destination . '/' . $readdirectory );
    		}
    		$directory->close();
    		}else {
    			copy( $source, $destination );
    		}
    	}
    Ok, je vais utiliser set_time_limit(0); avant le lancement de ma fonction

  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
    quand pensez-vous
    Assez souvent en général

    Mis à part le @ qui se tiend là comme une belle verrue et que la logique de contrôle laisse à désirer, elle à l'air de faire son travail.

    Cela étant, je trouve la mienne un poil plus simple et plus souple.

    Voici le bench que j'ai effectué:
    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
     
    function copy_directory($source,$destination ) {
    	if ( is_dir( $source ) ) {
    		@mkdir( $destination );
    		$directory = dir( $source );
    		while ( FALSE !== ( $readdirectory = $directory->read() ) ) {
    			if ( $readdirectory == '.' || $readdirectory == '..' ) {
    				continue;
    			}
    			$PathDir = $source . '/' . $readdirectory;
    			if ( is_dir( $PathDir ) ) {
    				copy_directory( $PathDir, $destination . '/' . $readdirectory );
    				continue;
    			}
    			copy( $PathDir, $destination . '/' . $readdirectory );
    		}
    		$directory->close();
    		}else {
    			copy( $source, $destination );
    		}
    	}
     
    function copy_dir ($from, $to, $reccursive = true, array & $files = null) {
        if (!is_dir($from) || !is_readable($from))
            throw new InvalidArgumentException("First parameter is not a valid directory or is not readable");
     
        if (!is_dir($to) || !is_writable($to))
            throw new InvalidArgumentException("Second parameter is not a vadlid directory or is not writeable");
     
        $from = realpath($from);
        $to   = realpath($to);
     
        if ($reccursive) {
            $dir = new RecursiveDirectoryIterator($from);
            $dir = new RecursiveIteratorIterator($dir);
        }
        else {
            $dir = new DirectoryIterator($from);
        }
     
        $files = array();
        foreach ($dir as $item) {
            $dirname          = realpath($item->getPath());
            $filename         = realpath($item->getPathname());
            $new_dirname      = str_replace($from, $to, $dirname);
            $new_filename     = str_replace($from, $to, $filename);
     
            if (!$reccursive && $item->isDir())
                continue;
            elseif(!isset($files[$new_dirname]) && !is_dir($new_dirname))
                $files[$new_dirname] = mkdir($new_dirname);
     
            $files[$new_filename] = copy($filename, $new_filename);
        }
     
        return !in_array(false, $files, true);
    }
     
    set_time_limit(0);
     
    define('SOURCE', 'D:/temp/test/1');
    define('DESTINATION', 'D:/temp/test/%s');
     
    echo "<pre>";
    for ($i = 0; $i < 10; $i++) {
      echo "TEST #$i\n";
      mkdir($dest_a = sprintf(DESTINATION, "$i.1"));
      mkdir($dest_b = sprintf(DESTINATION, "$i.2"));
     
      _st();
      copy_directory(SOURCE, $dest_a);
      echo "copy_directory() took " . _nd() . " seconds\n";
     
      _st();
      copy_dir(SOURCE, $dest_b);
      echo "copy_dir() took " . _nd() . " seconds\n";
    }
    Résultat:
    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
    TEST #0
    copy_directory() took 1.122 seconds
    copy_dir() took 2.201 seconds
    TEST #1
    copy_directory() took 2.876 seconds
    copy_dir() took 4.613 seconds
    TEST #2
    copy_directory() took 3.635 seconds
    copy_dir() took 3.054 seconds
    TEST #3
    copy_directory() took 2.643 seconds
    copy_dir() took 2.923 seconds
    TEST #4
    copy_directory() took 2.643 seconds
    copy_dir() took 2.301 seconds
    TEST #5
    copy_directory() took 2.466 seconds
    copy_dir() took 2.397 seconds
    TEST #6
    copy_directory() took 2.811 seconds
    copy_dir() took 2.837 seconds
    TEST #7
    copy_directory() took 3.259 seconds
    copy_dir() took 2.406 seconds
    TEST #8
    copy_directory() took 2.027 seconds
    copy_dir() took 1.604 seconds
    TEST #9
    copy_directory() took 1.964 seconds
    copy_dir() took 1.545 seconds
    On remarque que copy_directory() est relativement stable en performances alors que la rapidité de copy_dir() augmente avec le nombre d'itération (probablement dû au cache de PHP).

    Les tests ont été effectués avec un Core2 Duo 2.26Ghz et 2,86Mo de RAM (128Mo pour PHP) sous WinXP SP3 avec PHP 5.3.10 et un jeu de données de ~45Mo répartis sur 3 sous dossiers.

  11. #11
    Membre du Club
    Inscrit en
    Juillet 2009
    Messages
    201
    Détails du profil
    Informations forums :
    Inscription : Juillet 2009
    Messages : 201
    Points : 48
    Points
    48
    Par défaut
    Citation:
    quand pensez-vous

    Assez souvent en général
    Lool...

    Merci pour les résultats effectués !

    Si tu devais choisir tu prendrais quelle fonction ?
    copy_directory() est relativement stable | la rapidité de copy_dir() augmente avec le nombre d'itération
    Sachant que les copies peuvent être variables en terme de poid et de profondeur des dossiers...

  12. #12
    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
    Par sécurité, je prendrai copy_dir personnellement. Outre l'approche objet avec les itérateurs, la principale différence entre copy_directory et copy_dir est que la seconde est reccursive et donc est susceptible de consommer beaucoup d'espace mémoire. Il faudrait faire un test complet sur l'utilisation de la mémoire car je ne sais pas exactement comment le RecursiveDirectoryIterator occupe la mémoire quand il est traversé.
    Une autre raison est qu'avec copy_dir la recursivité est optionnelle (on peut la désactiver en mettant le paramètre $recursive à FALSE) et aussi qu'elle effectue plus de contrôle (notamment la vérification que les répertoires sont bien lisibles et inscriptibles) et enfin qu'elle renvoie le statut de la copie pour chaque fichier alors qu'avec copy_directory, on ne sait pas ce qui s'est passé une fois la fonction exécutée.

    Une amélioration possible serait la vérification de l'existence du fichier de destination avant copie (ce qui serait un peu coûteux en terme de temps) et l'ajout d'un flag pour écraser ou non le fichier de destination.

    Bref, j'ai toujours tendance à opter pour la solution la plus simple, mais à toi de voir en ton âme et conscience

  13. #13
    Expert éminent sénior

    Profil pro
    Inscrit en
    Septembre 2010
    Messages
    7 920
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2010
    Messages : 7 920
    Points : 10 726
    Points
    10 726
    Par défaut
    ça donne quoi le bench avec

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    function phar_copy($source , $dest) {
        $filename = tempnam(sys_get_temp_dir(), 'copy_').'.tar';
     
        $tar = new PharData($filename);
        $tar->buildFromDirectory($source);
     
        if (!is_dir($dest)) {
            mkdir($dest);
        }
     
        $tar->extractTo($dest, null, true);
     
        unlink($filename);
    }

  14. #14
    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
    Désolé stealth, les performances de phar_copy sont catastrophiques:
    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
    TEST #1
    copy_directory() took 0.945 seconds
    copy_directory() used 1 KB
    copy_dir() took 2.861 seconds
    copy_dir() used 5 KB
    phar_copy() took 17.618 seconds
    phar_copy() used 14 KB
    TEST #2
    copy_directory() took 3.782 seconds
    copy_directory() used 1 KB
    copy_dir() took 3.255 seconds
    copy_dir() used 4 KB
    phar_copy() took 17.019 seconds
    phar_copy() used 14 KB
    TEST #3
    copy_directory() took 2.699 seconds
    copy_directory() used 1 KB
    copy_dir() took 2.557 seconds
    copy_dir() used 4 KB
    phar_copy() took 15.993 seconds
    phar_copy() used 14 KB
    TEST #4
    copy_directory() took 2.417 seconds
    copy_directory() used 1 KB
    copy_dir() took 2.413 seconds
    copy_dir() used 4 KB
    phar_copy() took 15.237 seconds
    phar_copy() used 14 KB
    TEST #5
    copy_directory() took 4.164 seconds
    copy_directory() used 1 KB
    copy_dir() took 2.463 seconds
    copy_dir() used 4 KB
    phar_copy() took 16.311 seconds
    phar_copy() used 14 KB
    TEST #6
    copy_directory() took 2.629 seconds
    copy_directory() used 1 KB
    copy_dir() took 2.202 seconds
    copy_dir() used 4 KB
    phar_copy() took 17.332 seconds
    phar_copy() used 14 KB
    TEST #7
    copy_directory() took 2.005 seconds
    copy_directory() used 1 KB
    copy_dir() took 1.811 seconds
    copy_dir() used 4 KB
    phar_copy() took 14.612 seconds
    phar_copy() used 14 KB
    TEST #8
    copy_directory() took 1.982 seconds
    copy_directory() used 1 KB
    copy_dir() took 1.961 seconds
    copy_dir() used 4 KB
    phar_copy() took 15.726 seconds
    phar_copy() used 14 KB
    TEST #9
    copy_directory() took 1.961 seconds
    copy_directory() used 1 KB
    copy_dir() took 1.851 seconds
    copy_dir() used 4 KB
    phar_copy() took 19.905 seconds
    phar_copy() used 14 KB
    TEST #10
    copy_directory() took 1.931 seconds
    copy_directory() used 1 KB
    copy_dir() took 1.727 seconds
    copy_dir() used 4 KB
    phar_copy() took 15.441 seconds
    phar_copy() used 14 KB
    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
    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
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    function phar_copy($source , $dest) {
        global $memory_nd;
        $filename = tempnam(sys_get_temp_dir(), 'copy_').'.tar';
     
        $tar = new PharData($filename);
        $tar->buildFromDirectory($source);
     
        if (!is_dir($dest)) {
            mkdir($dest);
        }
     
        $tar->extractTo($dest);
     
        unlink($filename);
        $memory_nd = memory_get_usage();
    }
     
    function copy_directory($source,$destination ) {
            global $memory_nd;
    	if ( is_dir( $source ) ) {
    		@mkdir( $destination );
    		$directory = dir( $source );
    		while ( FALSE !== ( $readdirectory = $directory->read() ) ) {
    			if ( $readdirectory == '.' || $readdirectory == '..' ) {
    				continue;
    			}
    			$PathDir = $source . '/' . $readdirectory;
    			if ( is_dir( $PathDir ) ) {
    				copy_directory( $PathDir, $destination . '/' . $readdirectory );
    				continue;
    			}
    			copy( $PathDir, $destination . '/' . $readdirectory );
    		}
    		$directory->close();
    		}else {
    			copy( $source, $destination );
    		}
            $memory_nd = memory_get_usage();
    	}
     
    function copy_dir ($from, $to, $reccursive = true, array & $files = null) {
        global $memory_nd;
        if (!is_dir($from) || !is_readable($from))
            throw new InvalidArgumentException("First parameter is not a valid directory or is not readable");
     
        if (!is_dir($to) || !is_writable($to))
            throw new InvalidArgumentException("Second parameter is not a vadlid directory or is not writeable");
     
        $from = realpath($from);
        $to   = realpath($to);
     
        if ($reccursive) {
            $dir = new RecursiveDirectoryIterator($from);
            $dir = new RecursiveIteratorIterator($dir);
        }
        else {
            $dir = new DirectoryIterator($from);
        }
     
        $files = array();
        foreach ($dir as $item) {
            $dirname          = realpath($item->getPath());
            $filename         = realpath($item->getPathname());
            $new_dirname      = str_replace($from, $to, $dirname);
            $new_filename     = str_replace($from, $to, $filename);
     
            if (!$reccursive && $item->isDir())
                continue;
            elseif(!isset($files[$new_dirname]) && !is_dir($new_dirname))
                $files[$new_dirname] = mkdir($new_dirname);
     
            $files[$new_filename] = copy($filename, $new_filename);
        }
     
        $memory_nd = memory_get_usage();
        return !in_array(false, $files, true);
    }
     
    set_time_limit(0);
    error_reporting(0);
     
    define('SOURCE', 'D:/temp/test/1');
    define('DESTINATION', 'D:/temp/test/2/%s');
     
    $memory_nd = null;
     
    echo "<pre>";
    for ($i = 1; $i <= 10; $i++) {
      echo "TEST #$i\n";
      mkdir($dest_a = sprintf(DESTINATION, "$i.1"));
      mkdir($dest_b = sprintf(DESTINATION, "$i.2"));
      mkdir($dest_c = sprintf(DESTINATION, "$i.3"));
     
      _st();
      $memory_st = memory_get_usage();
      copy_directory(SOURCE, $dest_a);
      echo "copy_directory() took " . _nd() . " seconds\n";
      echo "copy_directory() used " . round(($memory_nd - $memory_st) / 1024) . " KB\n";
     
      _st();
      $memory_st = memory_get_usage();
      copy_dir(SOURCE, $dest_b);
      echo "copy_dir() took " . _nd() . " seconds\n";
      echo "copy_dir() used " . round(($memory_nd - $memory_st) / 1024) . " KB\n";
     
      _st();
      $memory_st = memory_get_usage();
      phar_copy(SOURCE, $dest_c);
      echo "phar_copy() took " . _nd() . " seconds\n";
      echo "phar_copy() used " . round(($memory_nd - $memory_st) / 1024) . " KB\n";
    }
    echo "</pre>";

  15. #15
    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
    Au final, je pense que cette solution est la meilleure que je peux trouver:
    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
    defined('FLAG_COPY_RECURSIVE') || define('FLAG_COPY_RECURSIVE', 1);
    defined('FLAG_COPY_OVERWRITE') || define('FLAG_COPY_OVERWRITE', 2);
     
    function copy_dir ($source, $destination, $flags = FLAG_COPY_RECURSIVE, array & $files = null) {
        if (!is_dir($source) || !is_readable($source))
            throw new UnexpectedValueException("Source is not readable or a valid directory");
     
        if (!is_dir($destination) || !is_writable($destination))
            throw new UnexpectedValueException("Destination is not writeable or a valid directory");
     
        $source      = realpath($source);
        $destination = realpath($destination);
        $dir_handle  = opendir($source);
        $files       = array();
        $recursive   = (bool)($flags & FLAG_COPY_RECURSIVE);
        $overwrite   = (bool)($flags & FLAG_COPY_OVERWRITE);
     
        while ($file = readdir($dir_handle)) {
            if ($file == '.' || $file == '..')
                continue;
     
            $old_path = "$source/$file";
            $new_path = "$destination/$file";
     
            if (is_dir($old_path)) {
                if ($recursive && !($exists = is_dir($new_path)))
                    $exists = mkdir($new_path);
                if ($recursive && $exists)
                    copy_dir($old_path, $new_path, $flags, $files);
            }
            elseif ($overwrite || !is_file($new_path)) {
                    $files[$new_path] = copy($old_path, $new_path);
            }
        }
        closedir($dir_handle);
        return !in_array(false, $files, true);
    }
     
    // usage
    _st();
    $overall = copy_dir('D:/temp/test/1', 'D:/temp/test/2', FLAG_COPY_OVERWRITE + FLAG_COPY_RECURSIVE, $files);
    var_dump(_nd(), $overall, $files);
    C'est l'équivalent de la tienne seb-65, j'ai juste ajouté deux flags pour paramétrer la récursivité et l'écrasement. J'ai aussi opté pour opendir plutôt que dir (qui est très mal documenté, jouons la sécurité) car c'est certainement disponible sur plus de version de PHP et c'est kiff kiff niveau perfs (en plus on est full procédural maintenant).

    Cette fonction affiche des perfs au niveau de la tienne, mais elle renvoie en plus le status (false si un seul fichier n'est pas déplacé, true sinon) ainsi qu'un tableau (le paramètre $files) qui pour chaque nouveau fichier te donne le status de copie.

    Enjoy.

    Si quelqu'un veut me mettre le nez dans le caca avec l'algo master, il est le bienvenu

  16. #16
    Membre émérite
    Avatar de gene69
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    1 769
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Janvier 2006
    Messages : 1 769
    Points : 2 446
    Points
    2 446
    Par défaut
    question, si $recursive est faux, $exists est quand même calculé?


    je comprends pas trop ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    !in_array(false, $files, true)
    dans ce cas, pourquoi pas ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     function copy_dir(...){
     $return = true;
     $return =  copy_dir(...) && $return;
     return $return;
    }
    PHP fait nativement la validation d'adresse électronique .
    Celui qui a inventé mysql_connect(...) or die() est déjà mort plusieurs fois.

    Utilisez le bouton résolu!

  17. #17
    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
    question, si $recursive est faux, $exists est quand même calculé?
    Non, la preuve en image:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    function say_something () {
    	echo "hello";
    }
     
    var_dump( false && say_something() ); // say_something n'est pas appellée
    var_dump( true && say_something() ); // say_something est appellée
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    !in_array(false, $files, true)
    ça dit "existe t'il une seule entrée dans $files qui soit strictement à false" (strictement veux dire faux et du type booléen). La négation peut donc s'interpréter "Il n'y a aucune entrée false dans $files".

    dans ce cas, pourquoi pas ? <code>
    Parce que c'est pas forcément récursif.

  18. #18
    Membre du Club
    Inscrit en
    Juillet 2009
    Messages
    201
    Détails du profil
    Informations forums :
    Inscription : Juillet 2009
    Messages : 201
    Points : 48
    Points
    48
    Par défaut
    Bonjour

    Benjamin Delespierre je vais prendre ta solution

    Au vue de tes résultats elle se rapproche de la mienne en terme de bench et elle intègre en plus la vérification de copie !!

    Merci.

Discussions similaires

  1. Eviter le message maximum execution time
    Par pelloq1 dans le forum Langage
    Réponses: 2
    Dernier message: 22/07/2008, 20h53
  2. [Joomla!] Installation composant:Fatal error: Maximum execution time
    Par copin dans le forum EDI, CMS, Outils, Scripts et API
    Réponses: 1
    Dernier message: 24/06/2008, 13h38
  3. [phpMyAdmin] maximum execution time 300 seconds - Je n'en veux plus
    Par lodan dans le forum EDI, CMS, Outils, Scripts et API
    Réponses: 4
    Dernier message: 30/08/2006, 11h09
  4. Réponses: 4
    Dernier message: 21/07/2006, 15h33
  5. Réponses: 5
    Dernier message: 19/05/2006, 10h38

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