PROJET AUTOBLOG


Tiger-222

Archivé

Site original : Tiger-222

⇐ retour index

PHP : is_file vs file_exists

lundi 14 octobre 2013 à 17:32
is_file, comme la documentation l'indique, vérifie si le fichier est un véritable fichier, tandis que file_exists vérifie si un fichier ou un dossier existe. À savoir que ces deux fonctions utilisent un système de cache, elles partent donc sur un pied d'égalité.

Les sources


Rien de mieux que le retour aux sources pour voir les entrailles de ces deux fonctions. Il s'avère qu'elles utilisent la même function en interne, seules les routines de vérification diffèrent.

Ci-dessous, le pseudo code très simplifié du processus de vérification :
function php_stat($fichier)
{
'file_exists'
↳ virtual_file_ex($fichier)
↳ virtual_access($fichier)
'Windows'
↳ tsrm_win32_access($fichier)
↳ return access($fichier)
'Autres systèmes'
↳ return access($fichier)
↳ return _php_stream_stat_path($fichier) == FALSE
'is_file'
↳ _php_stream_stat_path($fichier)
↳ return $fichier.st_mode == S_IFREG
}

Pour les curieux, voici les sources des fonctions :
Au premier abor, ça semble clair comme de l'eau de roche, file_exists() nécessite bien plus d'opérations à effectuer. Cependant, _php_stream_stat_path() est lourde puisqu'elle récupère toutes les informations sur un fichier/dossier (appelé inode) : volume, numéro d'inode, droit d'accès à l'inode, nombre de liens, userid du propriétaire, groupid du propriétaire, type du volume, si le volume est une inode, taille en octets, date de dernier accès (Unix timestamp), date de dernière modification (Unix timestamp), date de dernier changement d'inode (Unix timestamp), taille de bloc et le nombre de blocs de 512 octets alloués.

Il faudra attendre de voir le résultat des tests pour se faire une meilleure idée.


Une meilleure alternative ?


Dans ce commentaire, DeyV laisse à penser que stream_resolve_include_path serait une bonne alternative à file_exists(). À priori, cette fonction utiliserait aussi le système de cache.
Great alternative to file_exists() is stream_resolve_include_path() -- DeyV
Toujours d'après les sources, le pseudo code suivant en ressort :
function stream_resolve_include_path($fichier)
{
zend_resolve_path($fichier)
↳ php_resolve_path_for_zend($fichier)
↳ php_resolve_path($fichier)
↳ tsrm_realpath($fichier)
↳ return estrdup($fichier)
}

Pour les curieux, le détail de chaque fonction :
Notez que le fait d'utiliser des chemins absolus permet un gain non négligeable.


Les tests


Configuration de la machine de test


Le benchmark


Deux types de tests : un réaliste où on teste la présence de fichiers différents, et un autre moins parlant dans lequel le même fichier est testé 1 000 000 de fois.
Pour le test réaliste, j'ai créé un dossier test qui contient 1 000 000 fichiers (le premier fichier s'appelant 0 et le dernier 999999).
D'après le script qui permet de lancer et chronométrer les tests, le graphique suivant en résulte :



Observations



Historique


MàJ du 2013-10-23 : ajout des explications avec les sources PHP
MàJ du 2013-10-25 : Une meilleure alternative ?
MàJ du 2013-10-27 : ajout de tests plus réalistes et étoffement des informations
MàJ du 2013-10-28 : ajout du script de tests pour ne pas trop encombrer la page