Mauvais usage de la fonction array_shift

By | 11 décembre 2012

Aujourd’hui il m’est arrivé une petite mésaventure avec la fonction array_shift().

Cette fonction permet de retourner et supprimer le premier élément d’un tableau php. J’ai tendance à l’utiliser pour de lourd traitement en batch, ce qui me permet de libérer la mémoire au fur et à mesure du parcours du tableau.

Je ne m’étais jamais attardé sur cette fonction jusqu’à aujourd’hui. Devant traiter un gros tableau, j’utilise comme à mon habitude cette fonction, mais cette fois le script n’en finit pas. Je refais des tests sur un tableau contenant 2 fois moins d’éléments, et cette fois le temps de traitement est plutôt correct, mais rien à faire à partir d’un certain nombre d’éléments le temps de traitement accroit de manière exponentielle (0.008s par appel array_shift).

Cette fonction que j’utilise (à tord !) pour le parcours d’un tableau, supprime  les éléments au fur et à mesure et re-indexe entièrement le tableau de façon à ce que le premier élément du tableau soit toujours l’indice 0. Ce qui explique sa lenteur face à de gros tableau.

Si comme moi, vous utilisez array_shift uniquement pour libérer la mémoire au fur et à mesure du parcours de vos tableaux je vous conseille plutôt d’utiliser array_pop (si l’ordre de traitement du tableau n’a pas d’importance évidement) car il s’agit de la même fonction en interne (_phpi_pop).  La seule différence qui réside entre array_shift et array_pop c’est le placement du pointeur dans le tableau (dans un cas un appel à reset, et dans l’autre à array_end) et la re-indexation du tableau !

Test:

function getArray() {
        $array = range(1, 10000);
        foreach ($array as &$element) {
                $element = range(0, 1);
        }
        return  $array;
}

$array = getArray();
$begin = microtime(true);
while ($element = array_shift($array)) {
        ($element);
}
echo 'array_shift '.(microtime(true)-$begin)."\n";

$array = getArray();
$begin = microtime(true);
while ($element = array_pop($array)) {
        ($element);
}
echo 'array_pop '.(microtime(true)-$begin)."\n";

Résultat:
array_shift 1.3418190479279
array_pop 0.0079951286315918

Voilà, rien d’extraordinaire dans cet article, je voulais juste apporter cette petite précision concernant cette fonction qui m’a rendu fou pendant une petite demi heure (j’ai eu dû mal à la soupçonner) :p

Category: Php