J'ai donc modifié l'implémentation de ma classe dérivant de filterIterator :

...
class keyAsStringFilterIterator extends FilterIterator
{
protected $stringFound = true;

public function __construct(array $array)
{
asort($array);
parent::__construct(new arrayIterator($array));
}

public function rewind()
{
parent::rewind();
$this->stringFound = true;
}

public function valid()
{
return ($this->stringFound === true && parent::valid() === true);
}

public function accept()
{
if (is_string($this->key()) === false)
{
$this->stringFound = false;
}

return $this->stringFound;
}
}
...

Les plus attentifs auront remarqué que les closures ne sont plus utilisées, puisque l'itérateur est maintenant très fortement spécialisé, d’où son changement de nom.

Afin de ne pas pénaliser l'approche traditionnelle, j'ai également modifié son code de la manière suivante :

...
asort($array);

foreach ($array as $key => $value)
{
if (is_string($key) === true)
{
echo $value;
}
else
{
break;
}
}
...

Et les résultats, alors ?

Et bien j'aurais mieux fait d'essayer de dormir plutôt que de réfléchir à ce problème :

fch@diablo:~/tmp
37> php -nf bench.php
Iterator: abcdefghijklmnopqrstuvwxyz [0.64576697349548]
Foreach: abcdefghijklmnopqrstuvwxyz [0.26274108886719]
Delta: 0.3830258846283
Ratio: 2.4578073276613

L'itérateur reste plus de deux fois plus lent que la solution classique.

Vous me direz que c'est toujours mieux que d'être 7 fois plus lent et vous n'aurez pas tort.

Et comme quoi il n'est pas inutile d'essayer d'optimiser ses algorithmes, même si ca ne change pas la face du monde, cela permet de gagner de précieuse seconde.

Et curieusement, en chargeant mes extensions, le delta n'est plus deux fois mais bien huit fois plus important :

fch@diablo:~/tmp
40> php -f bench.php
Iterator: abcdefghijklmnopqrstuvwxyz [2.0768599510193]
Foreach: abcdefghijklmnopqrstuvwxyz [0.24072194099426]
Delta: 1.836138010025
Ratio: 8.6276304621056

Du coup, j'ai cette fois pris la peine d'investiguer, et l'extension xdebug est bien la responsable de ce phénomène puisqu'en la désactivant, je retrouve des résultats beaucoup plus similaires à ceux que j’obtiens avec les extensions désactivées.

Pour ceux qui veulent s'amuser, le code source complet est attaché à ce billet, et les tests ont été effectués dans les même conditions que dans le cadre de mon précédent billet.

Et cela n'a rien à voir avec ce qui précède, mais avec la publication de celui-ci, ce blog compte plus de 100 billets au compteur.