only - readdir php
readdir vs scandir (5)
1] ¿Cuál de las funciones es más rápida?
2] ¿Cuáles son las diferencias?
Differences
1] readdir devuelve el nombre de la siguiente entrada en el directorio. Scandir devuelve una matriz de archivos y directorios del directorio.
2] readdir debe tener un identificador de recursos abierto hasta que se lean todas las entradas. scandir, ¿tal vez crea una matriz de todas las entradas y cierra el control de recursos?
He hecho algunas pruebas. (Gracias a Aufziehvogel para la construcción)
$count = 100000;
$dir = dirname(__FILE__);
$startScan = microtime(true);
for ($i=0;$i<$count;$i++) {
$array = scandir($dir);
}
$endScan = microtime(true);
$startRead = microtime(true);
for ($i=0;$i<$count;$i++) {
$handle = opendir($dir);
while (false !== ($entry = readdir($handle))) {
// We do not know what to do
}
}
$endRead = microtime(true);
$startGlob = microtime(true);
for ($i=0;$i<$count;$i++) {
$array3 = glob(''*'');
}
$endGlob = microtime(true);
echo "scandir: " . ($endScan-$startScan) . "/n";
echo "readdir: " . ($endRead-$startRead) . "/n";
echo "glob : " . ($endGlob-$startGlob) . "/n";
Resultados del servidor Linux:
scandir: 0.82553291320801
readdir: 0.91677618026733
glob : 0.76309990882874
Esto se debe a 4 núcleos (8 hilos) Intel E3-1240 Cpu linux + servidor Apache.
Pero los resultados de los servidores de Windows son opuestos. Servidor Windows + Apache - Intel Q8400 4 Core (4 hilos)
Resultados del servidor Windows:
$count = 10000; // it was on linux 100000 :)
scandir: 0.61557507515
readdir: 0.614650011063
glob : 1.92112612724
(La carpeta incluye 13 archivos. Si los archivos aumentan, los resultados pueden ser diferentes)
Hice algunas comparaciones más de tiempo para leer un árbol de directorios completo con muchos archivos y directorios:
la llamada filetype () == "dir" es claramente más rápida que la llamada is_dir ()
las llamadas opendir / readdir son mucho más rápidas que el RecursiveDirectoryIterator
la construcción del árbol de directorios utilizando la profundidad de las llamadas recursivas primero o lineal no hace ninguna diferencia
Las pruebas anteriores se realizaron en Windows en SSD local, USB local y unidad de red con resultados consistentes. La ejecución en la unidad de red fue hasta 180 veces más lenta que las unidades locales, ¡a pesar de los gigabits y la unidad ReadyNAS más rápida!
El número de entradas manejadas por segundo varió desde 115 con el código más lento hasta la unidad de red hasta casi 65 000 para el código más rápido para la unidad USB 3.0, debido al almacenamiento en caché, por supuesto.
Pero la enorme diferencia para la unidad de red hace que se pregunte qué sucede dentro de PHP, ya que el comando dir simple y ls en Linux sobre los mismos archivos es mucho más rápido.
Continuará...
Realmente depende de lo que estés haciendo con los datos.
Si está pasando por entrada por entrada, debe usar readdir
, si realmente necesita tener una lista de las entradas en la memoria, debe usar scandir
.
No tiene sentido copiar información en la memoria cuando la vayas a usar entrada por entrada de todos modos. La evaluación perezosa es definitivamente el camino a seguir en ese caso.
Me imagino que scandir
es solo una envoltura alrededor de lo mismo que readdir
está llamando, y por lo tanto sería más lento.
Sé que esta pregunta puede no ser real ahora, pero para agregar he hecho algunas pruebas (como Aufziehvogel y Sayahan) con una pequeña diferencia, en un directorio con 1,000,000 de archivos pequeños (unos pocos bytes).
$dir = dirname(__FILE__) . ''/dir'';
$startScan = microtime(true);
$array = scandir($dir);
for ($i = 0, $j = count($array); $i < $j; $i++) {
// Code
}
$endScan = microtime(true);
unset($array);
$startRead = microtime(true);
$handle = opendir($dir);
while (false !== ($entry = readdir($handle))) {
// Code
}
$endRead = microtime(true);
unset($handle);
unset($entry);
$startDir = microtime(true);
$files = new DirectoryIterator($dir);
foreach ($files as $file) {
// Code
}
$endDir = microtime(true);
unset($files);
echo ''scandir: '', ($endScan - $startScan), PHP_EOL;
echo ''readdir: '', ($endRead - $startRead), PHP_EOL;
echo ''DirectoryIterator: '', ($endDir - $startDir), PHP_EOL;
Resultados (HDD):
scandir: 1.9403479099274
readdir: 0.79462885856628
DirectoryIterator: 0.5853099822998
Resultados (SSD):
scandir: 0.83593201637268
readdir: 0.35835003852844
DirectoryIterator: 0.28022909164429
CPU: AMD A10-4600M APU con gráficos Radeon (tm) HD (4 núcleos)
MEM: 8G
PHP: 5.6.29
Solo obteniendo los resultados (sin hacer nada), readdir es un mínimo más rápido:
<?php
$count = 10000;
$dir = ''/home/brati'';
$startScan = microtime(true);
for ($i=0;$i<$count;$i++) {
$array = scandir($dir);
}
$endScan = microtime(true);
$startRead = microtime(true);
for ($i=0;$i<$count;$i++) {
$handle = opendir($dir);
while (false !== ($entry = readdir($handle))) {
// We do not know what to do
}
}
$endRead = microtime(true);
echo "scandir: " . ($endScan-$startScan) . "/n";
echo "readdir: " . ($endRead-$startRead) . "/n";
Da:
== RUN 1 ==
scandir: 5.3707950115204
readdir: 5.006147146225
== RUN 2 ==
scandir: 5.4619920253754
readdir: 4.9940950870514
== RUN 3 ==
scandir: 5.5265231132507
readdir: 5.1714680194855
Entonces, por supuesto, depende de lo que intentes hacer. Si tiene que escribir otro bucle con scandir (), será más lento.