working not know how file_exists exist ejemplos delete php performance file-exists

know - if not exist file php



file_exists() es demasiado lento en PHP. ¿Alguien puede sugerir una alternativa más rápida? (19)

Al mostrar imágenes en nuestro sitio web, verificamos si el archivo existe con una llamada a file_exists() . Volvemos a una imagen ficticia si falta el archivo.

Sin embargo, la creación de perfiles ha demostrado que esta es la parte más lenta de generar nuestras páginas con file_exists() tomando hasta 1/2 ms por archivo. Solo estamos probando unos 40 archivos, pero esto aún lleva 20 ms al tiempo de carga de la página.

¿Alguien puede sugerir una forma de hacer que esto vaya más rápido? ¿Hay una mejor manera de probar si el archivo está presente? Si construyo un caché de algún tipo, ¿cómo debo mantenerlo sincronizado?


Volvemos a una imagen ficticia si faltaba el archivo

Si solo está interesado en recurrir a esta imagen ficticia, le recomendamos que permita que el cliente negocie con el servidor mediante una redirección (a la imagen ficticia) en el archivo no encontrado.

De esta forma, tendrá una pequeña sobrecarga de redirección y una demora no perceptible en el lado del cliente. Al menos te file_exists llamada "cara" (que no es, lo sé) a file_exists .

Solo un pensamiento.


¿Están todos en el mismo directorio? De ser así, puede valer la pena obtener la lista de archivos y almacenarlos en un hash y compararlos en lugar de todas las búsquedas file_exists.



Cree una rutina de hash para fragmentar los archivos en múltiples subdirectorios.

filename.jpg -> 012345 -> /01/23/45.jpg

Además, puede usar mod_rewrite para devolver su imagen de marcador de posición para las solicitudes a su directorio de imágenes que 404.


Creo que la mejor manera es mantener la URL de la imagen en la base de datos y luego ponerla en una variable de sesión, especialmente cuando tienes autenticación. De esta forma no tiene que estar revisando cada vez que una página se recarga


Cuando guarde un archivo en una carpeta, si la carga fue exitosa, puede almacenar la ruta a una Tabla DB.

Luego solo tendrá que hacer una consulta a la base de datos para encontrar la ruta del archivo solicitado.


Encuentro 1 / 2ms por llamada muy, muy asequible. No creo que haya alternativas mucho más rápidas, ya que las funciones de archivo están muy cerca de las capas inferiores que manejan las operaciones de archivos.

Sin embargo, puede escribir un contenedor en file_exists () que almacena los resultados en caché en un Memcache o recurso similar. Eso debería reducir el tiempo a casi nada en el uso diario.


La forma más rápida de verificar la existencia de un archivo local es stream_resolve_include_path() :

if (false !== stream_resolve_include_path($s3url)) { //do stuff }

Resultados de rendimiento stream_resolve_include_path () vs file_exists () :

Test name Repeats Result Performance stream_resolve 10000 0.051710 sec +0.00% file_exists 10000 0.067452 sec -30.44%

En la prueba se usaron rutas absolutas. La fuente de prueba está here . Versión de PHP:

PHP 5.4.23-1 ~ dotdeb.1 (cli) (construido: 13 de diciembre 2013 21:53:21)
Copyright (c) 1997-2013 The PHP Group
Zend Engine v2.4.0, Copyright (c) 1998-2013 Zend Technologies


Llegué a esta página buscando una solución, y parece que fopen puede hacer el truco. Si usa este código, es posible que desee deshabilitar el registro de errores para los archivos que no se encuentran.

<?php for ($n=1;$n<100;$n++){ clearstatcache(); $h=@fopen("files.php","r"); if ($h){ echo "F"; fclose($h); }else{ echo "N"; } } ?>


Ni siquiera estoy seguro de si esto será más rápido, pero parece que todavía te gustaría comparar tan bien:

Cree una caché de una gran variedad de todas las rutas de imágenes.

$array = array(''/path/to/file.jpg'' => true, ''/path/to/file2.gif'' => true);

Actualice el caché por hora o diariamente dependiendo de sus requisitos. Haría esto utilizando cron para ejecutar un script PHP que irá recursivamente por el directorio de archivos para generar el conjunto de rutas.

Cuando desee verificar si existe un archivo, cargue su matriz en caché y realice una comprobación simple de isset () para una búsqueda de índice de matriz rápida:

if (isset($myCachedArray[$imgpath])) { // handle display }

Todavía habrá sobrecarga de carga de la memoria caché, pero con suerte será lo suficientemente pequeño como para permanecer en la memoria. Si tiene varias imágenes que está revisando en una página, probablemente notará ganancias más significativas, ya que puede cargar la memoria caché en la carga de la página.



Podría hacer un cronjob para crear periódicamente una lista de imágenes y almacenarlas en DB / file / BDB / ...

Cada media hora debería estar bien, pero asegúrese de crear una interfaz para restablecer el caché en caso de agregar / eliminar archivos.

Y luego, también es fácil de ejecutar find. -mmin -30 -print0 en el shell y agregue nuevos archivos.


Pregunta anterior, voy a agregar una respuesta aquí. Para php 5.3.8, is_file () (para un archivo existente) es un orden de magnitud más rápido. Para un archivo no existente, los tiempos son casi idénticos. Para PHP 5.1 con eaccelerator, están un poco más cerca.

PHP 5.3.8 sin & sin APC

time ratio (1000 iterations) Array ( [3."is_file(''exists'')"] => 1.00x (0.002305269241333) [5."is_link(''exists'')"] => 1.21x (0.0027914047241211) [7."stream_resolve_inclu"(exists)] => 2.79x (0.0064241886138916) [1."file_exists(''exists'')"] => 13.35x (0.030781030654907) [8."stream_resolve_inclu"(nonexists)] => 14.19x (0.032708406448364) [4."is_file(''nonexists)"] => 14.23x (0.032796382904053) [6."is_link(''nonexists)"] => 14.33x (0.033039808273315) [2."file_exists(''nonexists)"] => 14.77x (0.034039735794067) )

PHP 5.1 con ecelerador

time ratio (1000x) Array ( [3."is_file(''exists'')"] => 1.00x (0.000458002090454) [5."is_link(''exists'')"] => 1.22x (0.000559568405151) [6."is_link(''nonexists'')"] => 3.27x (0.00149989128113) [4."is_file(''nonexists'')"] => 3.36x (0.00153875350952) [2."file_exists(''nonexists'')"] => 3.92x (0.00179600715637) [1."file_exists(''exists"] => 4.22x (0.00193166732788) )

Hay un par de advertencias.
1) No todos los "archivos" son archivos, is_file () prueba archivos regulares , no enlaces simbólicos. Por lo tanto, en un sistema * nix, no puede salirse con la suya solo con is_file () a menos que esté seguro de que solo está tratando con archivos regulares. Para cargas, etc., esto puede ser una suposición razonable, o si el servidor está basado en Windows, que en realidad no tiene enlaces simbólicos. De lo contrario, tendrás que probar is_file($file) || is_link($file) is_file($file) || is_link($file) .

2) El rendimiento definitivamente se degrada para todos los métodos si el archivo falta y se vuelve más o menos igual.

3) Mayor advertencia. Todos los métodos almacenan en caché las estadísticas del archivo para agilizar la búsqueda, de modo que si el archivo cambia de forma regular o rápida, se elimina, vuelve a aparecer, se borra y luego se borra la clearstatcache(); debe ejecutarse para garantizar que la información correcta de existencia de archivo se encuentre en la memoria caché. Así que los probé. Dejé fuera todos los nombres de archivo y tal. Lo importante es que casi todos los tiempos convergen, excepto stream_resolve_include, que es 4 veces más rápido. De nuevo, este servidor tiene eaccelerator, así que YMMV.

time ratio (1000x) Array ( [7."stream_resolve_inclu...;clearstatcache();"] => 1.00x (0.0066831111907959) [1."file_exists(...........;clearstatcache();"] => 4.39x (0.029333114624023) [3."is_file(................;clearstatcache();] => 4.55x (0.030423402786255) [5."is_link(................;clearstatcache();] => 4.61x (0.030798196792603) [4."is_file(................;clearstatcache();] => 4.89x (0.032709360122681) [8."stream_resolve_inclu...;clearstatcache();"] => 4.90x (0.032740354537964) [2."file_exists(...........;clearstatcache();"] => 4.92x (0.032855272293091) [6."is_link(...............;clearstatcache();"] => 5.11x (0.034154653549194) )

Básicamente, la idea es, si está 100% seguro de que es un archivo, no un enlace simbólico o un directorio, y con toda probabilidad, existirá, luego use is_file() . Verás una ganancia definitiva. Si el archivo puede ser un archivo o un enlace simbólico en cualquier momento, el archivo is_file () 14x + is_link () 14x ( is_file() || is_link() ) y será 2 is_file() || is_link() más lento en general. Si la existencia del archivo cambia MUCHO, entonces use stream_resolve_include_path ().

Por lo tanto, depende de su escenario de uso.


Si desea verificar la existencia de un archivo de imagen, ¡una forma mucho más rápida es usar getimagesize !

¡Más rápido localmente y remotamente!

if(!@GetImageSize($image_path_or_url)) // False means no imagefile { // Do something }


Si solo está buscando files existentes, use is_file() . file_exists() busca un archivo o directorio existente, por lo que quizás is_file() podría ser un poco más rápido.



file_exists() es almacenado en caché automáticamente por PHP. No creo que encuentre una función más rápida en PHP para verificar la existencia de un archivo.

Ver este hilo


Puntos de referencia con PHP 5.6:

Archivo existente:

0.0012969970 : stream_resolve_include_path + include 0.0013520717 : file_exists + include 0.0013728141 : @include

Archivo inválido:

0.0000281333 : file_exists + include 0.0000319480 : stream_resolve_include_path + include 0.0001471042 : @include

Carpeta inválida:

0.0000281333 : file_exists + include 0.0000360012 : stream_resolve_include_path + include 0.0001239776 : @include

Código:

// microtime(true) is less accurate. function microtime_as_num($microtime){ $time = array_sum(explode('' '', $microtime)); return $time; } function test_error_suppression_include ($file) { $x = 0; $x = @include($file); return $x; } function test_file_exists_include($file) { $x = 0; $x = file_exists($file); if ($x === true) { include $file; } return $x; } function test_stream_resolve_include_path_include($file) { $x = 0; $x = stream_resolve_include_path($file); if ($x !== false) { include $file; } return $x; } function run_test($file, $test_name) { echo $test_name . ":/n"; echo str_repeat(''='',strlen($test_name) + 1) . "/n"; $results = array(); $dec = 10000000000; // digit precision as a multiplier $i = 0; $j = 0; $time_start = 0; $time_end = 0; $x = -1; $time = 0; $time_start = microtime(); $x= test_error_suppression_include($file); $time_end = microtime(); $time = microtime_as_num($time_end) - microtime_as_num($time_start); $results[$time*$dec] = ''@include''; $i = 0; $j = 0; $time_start = 0; $time_end = 0; $x = -1; $time = 0; $time_start = microtime(); $x= test_stream_resolve_include_path_include($file); $time_end = microtime(); $time = microtime_as_num($time_end) - microtime_as_num($time_start); $results[$time * $dec] = ''stream_resolve_include_path + include''; $i = 0; $j = 0; $time_start = 0; $time_end = 0; $x = -1; $time = 0; $time_start = microtime(); $x= test_file_exists_include($file); $time_end = microtime(); $time = microtime_as_num($time_end) - microtime_as_num($time_start); $results[$time * $dec ] = ''file_exists + include''; ksort($results, SORT_NUMERIC); foreach($results as $seconds => $test) { echo number_format($seconds/$dec,10) . '' : '' . $test . "/n"; } echo "/n/n"; } run_test($argv[1],$argv[2]);

Ejecución de línea de comando:

php test.php ''/path/to/existing_but_empty_file.php'' ''Existing File'' php test.php ''/path/to/non_existing_file.php'' ''Invalid File'' php test.php ''/path/invalid/non_existing_file.php'' ''Invalid Folder''


Use rutas absolutas! Dependiendo de su configuración include_path , PHP verifica todos (!) Estos directorios si se comprueban las rutas de archivos relativas. Puede desarmar include_path temporalmente antes de verificar la existencia.

realpath() hace lo mismo, pero no sé si es más rápido.

Pero la E / S de acceso a archivos siempre es lenta. Un acceso al disco duro ES más lento que el cálculo de algo en el procesador, normalmente.