por only nombre mostrar listado is_dir files directorio buscar archivos php

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.