Style de codage

Eléphant du PHP | 275 Messages

20 sept. 2011, 17:20

unset($tab[5]);

devlop78
Invité n'ayant pas de compte PHPfrance

20 sept. 2011, 17:24

Je réaffirme deux choses : Il est rare de se battre pour si peu de différence alors même que tu itères sur 250 000 items. Et de deux, ce n'est pas adapté aux tableaux associatifs ou à trous.

Mais, parce que avec moi il y a toujours un mais (c'est bon l'auto-dérision), c'est toujours bien à savoir, et ça peut aider sur des cas particuliers d'algorithme.

Essai avec une modification au moins une fois dans le for() et foreach() pour provoquer le copy on write de php. Je pense que la différence sera encore plus flagrande.
Petit benchmark
<?php

$tab = array();

for($i=0; $i<250000; $i++) {
	array_push($tab, $i);
}

$var = '';
$t1 = microtime(true);
$m1 = memory_get_usage();
$ct = count($tab);
for($i=0; $i<$ct; $i++) {
	$var .= $i;
}
$t2 = microtime(true);
$m2 = memory_get_usage();
$diff1 = $t2 - $t1;
$mdiff1 = $m2 - $m1;

$var = '';
$t1 = microtime(true);
$m1 = memory_get_usage();
foreach($tab as $i) {
	$var .= $i;
}
$t2 = microtime(true);
$m2 = memory_get_usage();
$diff2 = $t2 - $t1;
$mdiff2 = $m2 - $m1;

echo 'for time: '.$diff1.''."\n";
echo 'for mem: '.$mdiff1.''."\n";
echo 'foreach time: '.$diff2.''."\n";
echo 'foreach mem: '.$mdiff2.''."\n";
Mes résultats sont sensiblement constants un exemple de résultat serait:
for time: 0.03811502456665
for mem: 1389512
foreach time: 0.040256023406982
foreach mem: 1388808
Ce qui montre que le for est plus rapide que le foreach, en revanche le foreach est effectivement moins gourmand en mémoire, bien sur on parle de pas grand chose mais voila.

devlop78
Invité n'ayant pas de compte PHPfrance

20 sept. 2011, 17:27

Pour être valable sur tous les types de tableaux on peut taper sur next() etc pour le while :

while ($a = next($machin))
{

}

Comme ça il avance le curseur sans se préoccuper de la suite numérique.
J'ai rajouté le while augmenter la ram le nombre d'occurences et un coup de shuffle
<?php

ini_set('memory_limit', '1024M');
$truemem = false;

$tab = array();

for($i=0; $i<250000; $i++) {
	array_push($tab, $i);
}
shuffle($tab);

$var = '';
$t1 = microtime(true);
$m1 = memory_get_usage($truemem);
$ct = count($tab);
for($i=0; $i<$ct; $i++) {
	$var = $i . $tab[$i];
}
$t2 = microtime(true);
$m2 = memory_get_usage($truemem);
$diff1 = $t2 - $t1;
$mdiff1 = $m2 - $m1;

$var = '';
$t1 = microtime(true);
$m1 = memory_get_usage($truemem);
foreach($tab as $num=>$i) {
	$var = $num . $i;
}
$t2 = microtime(true);
$m2 = memory_get_usage($truemem);
$diff2 = $t2 - $t1;
$mdiff2 = $m2 - $m1;

$var = '';
$t1 = microtime(true);
$m1 = memory_get_usage($truemem);
$ct = count($tab);
$i=0;
while($i < $ct) {
	$var = $i . $tab[$i];
	$i++;
}
$t2 = microtime(true);
$m2 = memory_get_usage($truemem);
$diff3 = $t2 - $t1;
$mdiff3 = $m2 - $m1;

echo 'for time: '.$diff1.''."\n";
echo 'for mem: '.$mdiff1.''."\n";
echo 'foreach time: '.$diff2.''."\n";
echo 'foreach mem: '.$mdiff2.''."\n";
echo 'while time: '.$diff3.''."\n";
echo 'while mem: '.$mdiff3.''."\n";
for time: 0.10704684257507
for mem: 632
foreach time: 0.093402862548828
foreach mem: 136
while time: 0.1063129901886
while mem: 88
avantage à foreach, mais pas un gros avantage, je vais voir si je peut trouver un cas ou le foreach est moins bon, en jouant sur ce qui se passe à l'intérieur des boucles.

devlop78
Invité n'ayant pas de compte PHPfrance

20 sept. 2011, 17:28

unset($tab[5]);
Un E_NOTICE + 1 null + le dernier oublié

Mammouth du PHP | 672 Messages

20 sept. 2011, 17:31

Petit benchmark
(...)
Ce qui montre que le for est plus rapide que le foreach, en revanche le foreach est effectivement moins gourmand en mémoire, bien sur on parle de pas grand chose mais voila.
J'avais lu une étude qui produisait plus ou moins le même résultat (variable suivant la version de PHP entre autres).
Vu la différence, on est dans le domaine de la micro-optimisation.

Mon avis sur la micro-optimisation en général : si on en arrive à essayer de grapiller des micro-secondes/octets de mémoire, c'est qu'il y a un problème de conception :mrgreen:

De plus, vu le peu de différences (et sachant que cette différence joue en faveur de l'un ou de l'autre suivant les versions de PHP), je privilégie la lisibilité.
Et de ce point de vue, je trouve le foreach plus clair. Donc...

devlop78
Invité n'ayant pas de compte PHPfrance

20 sept. 2011, 17:42

Rien qu'un include est plus long que un foreach normal (pas sur 250 000 items quoi ...), faut-il pour autant s'empêcher d'avoir une classe par fichier, ou plutôt mettre en place des caches d'Op-codes et de vues finales (voire de pages complètes si tout est statique pour une période T).

Eléphant du PHP | 275 Messages

20 sept. 2011, 17:54

unset($tab[5]);
Un E_NOTICE + 1 null + le dernier oublié
Je suis pas sur de comprendre ce que tu veux dire, mais comme tu l'as dit précédement, foreach fonctionne très bien pour les listes à trou, contrairement aux for & while.

Donc, performances ridiculement meilleures dans certains cas + meilleure lisibilité + moins de code = j'utilise foreach :)

devlop78
Invité n'ayant pas de compte PHPfrance

20 sept. 2011, 18:08

Ce que je veux dire ?

$array = array(0,1,2,3,4);
unset($array[2]);

for ($i=0;$i<count($array);$i++)
{
echo $array[$i];
}

Affichera :

01

NOTICE ERROR : Undefined index 2 in $array line x file y

3

$array[2] devenant implicitement null à l'appel (comme toute variable inexistante ou sans attribution de valeur). Et le "4" ne s'affichera pas (oui count n'est pas l'équivalent de Array.length en JavaScript ;))

Donc à moins d'utiliser des piles (qui sont logiquement sans trou) Array, ce sera soit Foreach soit While. Et je préfère foreach (d'autant qu'il est vraiment prévu pour l'itération, c'est sa tache dédiée !).

Eléphant du PHP | 275 Messages

20 sept. 2011, 18:17

Oki (mon incompréhension était purement syntaxique). On est donc d'accord :)

Enfin, les piles ça se gère pas mal à coup de array_shift/unshift quand même

ViPHP
ViPHP | 3300 Messages

20 sept. 2011, 18:21

pour boucler avec un for sur un tableau troué ou indéxé avec du texte y'a array_keys($arr) aussi, pour boucler sur un object y'a array_keys(get_object_vars($obj)), si je disais du mal de foreach c'est que j'avais passé du temps à optimiser du code y'a un bout de temps et l'optimisation principale consistait à virer les foreach, mais bon la mes tests c'est du php 5.3.8 peut-être qu'il y'avait un facteur bug, ou autre à l'époque qui n'est plus vrai maintenant.
Fait du php depuis que ca existe ou presque :)

devlop78
Invité n'ayant pas de compte PHPfrance

20 sept. 2011, 18:25

Oki (mon incompréhension était purement syntaxique). On est donc d'accord :)

Enfin, les piles ça se gère pas mal à coup de array_shift/unshift quand même
C'est pas top niveau perf, et là vraiment, surtout le FIFO. Mais je précise Array, puisqu'une pile peut être objet, et la SPL propose des piles.

devlop78
Invité n'ayant pas de compte PHPfrance

20 sept. 2011, 18:32

Sans vouloir me venter, les benchmarks que j'ai mis sont intéressants :

Un unset() sur un élément de fin de tableau est près de 8 fois plus rapide que un array_pop. Les pire sont les modifications en début ou milieu de tableau, d'après moi parce qu'ils doivent repositionner les index (donc parcourir toute une partie du tableau pour déplacer les clés).

devlop78
Invité n'ayant pas de compte PHPfrance

20 sept. 2011, 18:40

Et pour revenir au pseudo tableau numérique (qui n'est qu'un tableau associé en fait) :
<?php
$a = array (5=>'cinq',7=>'sept',2=>'deux');
array_shift($a);
var_dump($a);
affichera
0 => string 'sept' (length=4)
1 => string 'deux' (length=4)
L'importance n'est pas la clé, mais la place de l'élément dans le tableau. C'est aussi pour ça que je ne donne aucune importance à la clé avec PHP, et que je n'utilise plus for(). A l'extreme while(list($cle,$valeur) = each()) est plus logique que for, on est vraiment sur une notion de pointeur.

ViPHP
ViPHP | 3300 Messages

20 sept. 2011, 18:41

Sans vouloir me venter
ça veut dire coller un vent? :)
Fait du php depuis que ca existe ou presque :)

devlop78
Invité n'ayant pas de compte PHPfrance

20 sept. 2011, 18:46

Rhooo vu toutes les fautes sur l'ensemble du forum, je peux bien moi aussi en faire de temps en tant (<= hi hi hi)

Par contre j'adore être hors sujet, comme : Quelqu'un sait où on peut acheter l'éléphant peluche PHP ?