J'ai donc écrit le code suivant :

closure = $closure;
}

public function accept()
{
return ($this->closure->__invoke($this) === true);
}
}

$letters = str_split('abcdefghijklmnopqrstuvwxyz');
$array = array_combine($letters, $letters) + range(1, 100000);

echo 'Iterator: ';

$start = microtime(true);

foreach (new closureFilterIterator(new arrayIterator($array), function(\iterator $iterator) { return is_string($iterator->key()); }) as $key => $value)
{
echo $value;
}

$time1 = (microtime(true) - $start);

echo ' [' . $time1 . ']' . "\n";

echo 'Foreach: ';

$start = microtime(true);

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

$time2 = (microtime(true) - $start);

echo ' [' . $time2 . ']' . "\n";

echo 'Delta: ' . ($time1 - $time2) . "\n";
echo 'Ratio: ' . ($time1 / $time2) . "\n";

?>

Rien de bien particulier, si ce n'est l'utilisation de la méthode magique __invoke() pour appeler la closure vu que PHP c'est de la merde qu'il n'est pas possible d'appeler une closure de la manière normale si cette dernière est une propriété d'objet.

Pour votre information, j'ai entendu dire que ce point serait amélioré dans la prochaine version du langage, même si je n'ai pas l'ombre d'une confirmation de cela pour le moment.

Et les résultats, alors ?

Ils ont été sans appel.

L’exécution du code ci-dessus sur ma machine de développement en ligne de commande m'a donné les résultats suivant :

fch@diablo:~/tmp
8> php -nf closureFilterIterator.php
Iterator: abcdefghijklmnopqrstuvwxyz [0.39656400680542]
Foreach: abcdefghijklmnopqrstuvwxyz [0.055746793746948]
Delta: 0.34081721305847
Ratio: 7.113664843319

La méthode qui met en oeuvre filterIterator est donc 7 fois plus lente que celle utilisant l'instruction foreach et la fonction is_string().

Nous pourrions nous arrêter là, mais les plus attentifs auront remarqué l'utilisation du paramètre -n, qui permet de ne pas charger en mémoire les modules additionnels de PHP, ceci afin d'éliminer l'influence d'extension tel qu'APC ou xdebug.

Si je n'utilise pas ce paramètre, j'obtiens les résultats suivant :

fch@diablo:~/tmp
9> php -f closureFilterIterator.php
Iterator: abcdefghijklmnopqrstuvwxyz [2.8110311031342]
Foreach: abcdefghijklmnopqrstuvwxyz [0.51954388618469]
Delta: 2.2914872169495
Ratio: 5.4105748867091

Oui, vous avez bien lu, bizarrement, non seulement les deux méthodes prennent plus de temps, mais le delta entre les deux est moins significatif...

J'avoue ne pas avoir pris le temps de chercher la ou les extensions responsables de ce phénomène, même si je pense très fortement que le coupable est xdebug.

Conclusion, mettre en oeuvre la SPL n'est pas forcément la meilleure de choses à faire en terme de performance, et charger en mémoire des modules PHP non indispensables au fonctionnement du code en production n'est pas non plus une bonne idée.

Mais bon, la SPL, cela permet d'écrire quand même du bien joli code...

Pour ceux qui veulent se la mesurer les fans de comparaisons, le fichier contenant le code est attaché à ce billet et voici quelques informations complémentaires :

fch@diablo:~/tmp
10> uname -a
FreeBSD diablo.local 7.1-RELEASE-p9 FreeBSD 7.1-RELEASE-p9 #9: Thu Dec 10 13:41:18 CET 2009 root@diablo.local:/usr/obj/usr/src/sys/DIABLO i386
fch@diablo:~/tmp
11> php --version
PHP 5.3.1 with Suhosin-Patch (cli) (built: Dec 10 2009 17:57:41)
Copyright (c) 1997-2009 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2009 Zend Technologies
with Xdebug v2.0.5, Copyright (c) 2002-2008, by Derick Rethans
with Suhosin v0.9.29, Copyright (c) 2007, by SektionEins GmbH
fch@diablo:~/tmp
12> php -m
[PHP Modules]
bcmath
bz2
calendar
Core
ctype
curl
date
dom
ereg
exif
expect
fileinfo
filter
ftp
gd
gettext
gmp
hash
iconv
imagick
imap
json
ldap
libxml
mbstring
mcrypt
mdbtools
memcache
mhash
mssql
mysql
mysqli
mysqlnd
odbc
openssl
pcntl
pcre
pdf
PDO
pdo_mysql
pdo_sqlite
pgsql
posix
pspell
readline
recode
Reflection
session
shmop
SimpleXML
snmp
soap
sockets
SPL
SQLite
standard
suhosin
svn
sysvmsg
sysvsem
sysvshm
tidy
tokenizer
wddx
xdebug
xml
xmlreader
xmlrpc
xmlwriter
xsl
yaz
zip
zlib

[Zend Modules]
Xdebug

J'ajouterais que contrairement aux apparences, ce billet n'est sponsorisé ni par l'Académie Française, ni par la DGLFLF.