Digamos que estamos usando ext4 (con dir_index habilitado) para alojar alrededor de 3M de archivos (con un tamaño promedio de 750 KB) y necesitamos decidir qué esquema de carpeta vamos a usar.
En la primera solución , aplicamos una función hash al archivo y usamos una carpeta de dos niveles (siendo 1 carácter para el primer nivel y 2 caracteres para el segundo nivel): por lo tanto, siendo el filex.for
hash igual a abcde1234 , lo almacenaremos en / ruta / a / bc /abcde1234-filex.for.
En la segunda solución , aplicamos una función hash al archivo y usamos una carpeta de dos niveles (que son 2 caracteres para el primer nivel y 2 caracteres para el segundo nivel): por lo tanto, siendo el filex.for
hash igual a abcde1234 , lo almacenaremos en / ruta / ab / de /abcde1234-filex.for.
Para la primera solución tendremos el siguiente esquema /path/[16 folders]/[256 folders]
con un promedio de 732 archivos por carpeta (la última carpeta, donde residirá el archivo).
Mientras que en la segunda solución tendremos /path/[256 folders]/[256 folders]
un promedio de 45 archivos por carpeta .
Teniendo en cuenta que vamos a escribir / desvincular / leer archivos ( pero principalmente leídos ) de este esquema mucho (básicamente el sistema de almacenamiento en caché nginx), ¿ importa, en un sentido de rendimiento, si elegimos una u otra solución?
Además, ¿cuáles son las herramientas que podríamos usar para verificar / probar esta configuración?
fuente
hdparm -Tt /dev/hdX
pero podría no ser la herramienta más apropiada.hdparm
no es la herramienta adecuada, es una verificación del rendimiento sin procesar del dispositivo de bloque y no una prueba del sistema de archivos.Respuestas:
La razón por la que uno crearía este tipo de estructura de directorios es que los sistemas de archivos deben ubicar un archivo dentro de un directorio, y cuanto más grande sea el directorio, más lenta será esa operación.
Cuánto más lento depende del diseño del sistema de archivos.
El sistema de archivos ext4 utiliza un árbol B para almacenar entradas de directorio. Se espera que una búsqueda en esta tabla tome tiempo O (log n) , que la mayoría de las veces es menor que la tabla lineal ingenua que usaban ext3 y los sistemas de archivos anteriores (y cuando no lo es, el directorio es demasiado pequeño para que pueda realmente importa).
El sistema de archivos XFS utiliza un árbol B + en su lugar. La ventaja de esto sobre una tabla hash o un árbol B es que cualquier nodo puede tener varios hijos b , donde en XFS b varía y puede ser tan alto como 254 (o 19 para el nodo raíz; y estos números pueden estar desactualizados ) Esto le da una complejidad de tiempo de O (log b n) , una gran mejora.
Cualquiera de estos sistemas de archivos puede manejar decenas de miles de archivos en un solo directorio, con XFS siendo significativamente más rápido que ext4 en un directorio con el mismo número de inodes. Pero probablemente no desee un solo directorio con inodos de 3M, ya que incluso con un árbol B + la búsqueda puede llevar algún tiempo. Esto es lo que llevó a crear directorios de esta manera en primer lugar.
En cuanto a sus estructuras propuestas, la primera opción que dio es exactamente lo que se muestra en los ejemplos de nginx. Funcionará bien en cualquiera de los sistemas de archivos, aunque XFS aún tendrá una pequeña ventaja. La segunda opción puede funcionar un poco mejor o un poco peor, pero probablemente estará bastante cerca, incluso en los puntos de referencia.
fuente
ls -l
lleva un minuto completo si el directorio se ha caído del caché de inodo. Y cuando se almacena en caché, todavía lleva más de un segundo. Esto es con un SSD y un Xeon con toneladas de RAM en un servidor web de poco tráfico.En mi experiencia, uno de los factores de escala es el tamaño de los inodes dada una estrategia de partición de nombre hash.
Ambas opciones propuestas crean hasta tres entradas de inodo para cada archivo creado. Además, los archivos 732 crearán un inodo que aún es inferior a los 16 KB habituales. Para mí, esto significa que cualquiera de las opciones realizará lo mismo.
Te aplaudo en tu corto hash; Los sistemas anteriores en los que he trabajado han tomado la suma del archivo dado y los directorios empalmados basados en esa cadena, un problema mucho más difícil.
fuente
Ciertamente, cualquiera de las opciones ayudará a reducir la cantidad de archivos en un directorio a algo que parezca razonable, para xfs o ext4 o cualquier sistema de archivos. No es obvio cuál es mejor, tendría que probarlo para contarlo.
El punto de referencia con su aplicación que simula algo como la carga de trabajo real es ideal. De lo contrario, invente algo que simule muchos archivos pequeños específicamente. Hablando de eso, aquí hay uno de código abierto llamado archivo pequeño . Su documentación hace referencia a algunas otras herramientas.
hdparm
hacer E / S sostenidas no es tan útil. No mostrará las muchas E / S pequeñas o entradas de directorio gigantes asociadas con muchos archivos.fuente
Uno de los problemas es la forma de escanear la carpeta.
Imagine el método Java que ejecuta el escaneo en la carpeta.
Tendrá que asignar una gran cantidad de memoria y desasignarla en un corto período de tiempo, lo cual es muy pesado para la JVM.
La mejor manera es organizar la estructura de carpetas de la manera en que cada archivo está en una carpeta dedicada, por ejemplo, año / mes / día.
La forma en que se realiza el escaneo completo es que para cada carpeta hay una ejecución de la función, por lo que JVM saldrá de la función, desasignará la RAM y la ejecutará nuevamente en otra carpeta.
Esto es solo un ejemplo, pero de todos modos tener una carpeta tan grande no tiene sentido.
fuente
He estado teniendo el mismo problema. Intentando almacenar millones de archivos en un servidor Ubuntu en ext4. Terminé ejecutando mis propios puntos de referencia. Descubrí que el directorio plano funciona mucho mejor y es más simple de usar:
Escribió un artículo .
fuente