©
. Document créé le 19 avril 2011 , mis à jour le 19 avril 2011.Une personne qui n'a jamais commis d'erreurs n'a jamais tenté d'innover. Albert Einstein
Accueil du site > Astuces > PHP > Transmettre un paramètre par copie ou référence
Deux méthodes classiques pour transmettre un paramètre à une fonction :
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.
Les forums sont fermés.