Transmettre un paramètre par copie ou référence

© Christian PAULUS. Document créé le 19 avril 2011 , mis à jour le 19 avril 2011.

L'éternité c'est long, surtout vers la fin. Woody Allen

Accueil du site > Astuces > PHP > Transmettre un paramètre par copie ou référence

Comparatif / PHP 5

Deux méthodes classiques pour transmettre un paramètre à une fonction :

  • par copie de l’objet
  • par référence.

Dans le premier cas, c’est l’objet complet qui est recopié avant transmission à la fonction. Et si l’objet est de grande taille, l’impact sur la performance n’est pas insignifiant.

Dans le second cas, la fonction appelée a directement accès au réel contenu de l’objet. Il peut le modifier en tout ou partie. Ce qui peut provoquer quelques dysfonctionnements.

Il est d’usage de protéger un objet en ne transmettant qu’une copie de celui-ci. Est-ce un bon choix ?

Un test comparatif des deux méthodes :

<?php

/**
 * test comparatif performance
 * d'appel de fonction en transmettant
 * le paramètre :
 * - soit par copie de l'objet
 * - soit par référence
 *
 * @since PHP 5.3
 * @see http://www.quesaco.org/Transmettre-un-parametre-par-copie-ou-reference
 */

$eol = ((PHP_SAPI == 'cli') ? '' '<br />')
    .
PHP_EOL
    
;

/**
 * La première fonction à tester.
 * Ne fait rien.
 * Ne sert qu'à recevoir un paramètre
 * Ici, transmis par copie
 */
function par_copie ($var) {}

/**
 * La seconde fonction à tester.
 * Ne fait rien.
 * Ne sert qu'à recevoir un paramètre
 * Ici, transmis par référence
 */
function par_reference (& $var) {}

function 
tester_fonction ($funct$legend '')
{

    
// grosse variable à référencer
    // pour résultat significatif
    
static $item;
    static 
$sizeof;
    if (!
$item)
    {
        
$item = array();
        
// 1000 pour un var de 15 K
        // 100 pour 1.5 K
        
for ($ii 0$ii<1000$ii++)
        {
            
$item[] = 'un peu de texte';
        }
        
$sizeof strlen(implode(''$item));
    }
    
    
// lancer le chrono
    
$start microtime(1);

    
// boucle de test
    
for ( $ii 0$ii 10000$ii++ )
    {
        
$funct$item );
    }

    
// calculer le chrono
    
$result microtime(1) - $start;
    
    
$legend $legend ?: $funct;
    
    return (
$legend.': (sizeof:'.$sizeof.') '.$result' μs');
    
}

echo (
      
tester_fonction ('par_copie',
                 
'Par copie d\'objet:     ')
      . 
$eol
      
tester_fonction ('par_reference',
                 
'Par référence d\'objet: ')
      . 
$eol
      
);

?>

Lancer le test 3 ou 4 fois pour obtenir une moyenne correcte (la première fois, c’est toujours plus lent. Swap du système ?).

Quelques résultats (ici, en PHP 5.3.6) :

Dans le cas d’un tableau dont la taille est de 15 K :

Par copie d'objet:     : (sizeof:15000) 0.70829701423645 μs
Par référence d'objet: : (sizeof:15000) 0.0053398609161377 μs

142 fois plus rapide.

Moins évident lorsque l’objet à copier/transmettre est de 1.5K :

Par copie d'objet:     : (sizeof:1500) 0.073298931121826 μs
Par référence d'objet: : (sizeof:1500) 0.0055201053619385 μs

15 fois plus rapide, tout de même.

Plussoyez !

Les forums sont fermés.

  • Bonjour,

    Si j’ai bien compris, l’intérêt de PHP est assez limité. Autant tout tramestre sous forme de pointeur.

    Déjà que le mode objet me semblait peu performant

    Les forums sont fermés.

    • Transmettre un paramètre par copie ou référence 23 avril 2011 12:27, par Christian PAULUS

      L’intérêt de transmettre par copie plutôt.

      J’en arrive à la même conclusion.

      Et j’ai aussi le même a priori sur la POO. Pratique pour la maintenance, mais depuis que les espaces de nom existent, j’en vois peu l’intérêt.

      Les forums sont fermés.

      • Transmettre un paramètre par copie ou référence 25 avril 2011 19:03, par Olibe

        Ca m’étonne qu’à moitié. PHP est un langage interprété.

        Faire de l’objet me semblait déjà sans grand intérêt. Et maintenant, coder sale est parfois plus performant.

        Les forums sont fermés.