linux language-agnostic filesystems

linux - Reducir los tiempos de búsqueda al leer muchos archivos pequeños



language-agnostic filesystems (5)

¿podría recomendar el uso de una SSD para el almacenamiento de archivos? eso debería reducir los tiempos de búsqueda en gran medida ya que no hay cabeza para moverse.

Necesito escribir algún código (en cualquier idioma) para procesar 10.000 archivos que residen en un sistema de archivos Linux local. Cada archivo tiene un tamaño de ~ 500 KB y consta de registros de tamaño fijo de 4 KB cada uno.

El tiempo de procesamiento por registro es insignificante, y los registros se pueden procesar en cualquier orden, tanto dentro como a través de diferentes archivos.

Una implementación ingenua leería los archivos uno por uno, en un orden arbitrario. Sin embargo, como mis discos son muy rápidos de leer pero lentos de buscar, es casi seguro que producirán código vinculado a las búsquedas de disco.

¿Hay alguna forma de codificar la lectura para que esté vinculada al rendimiento del disco en lugar de buscar tiempo?

Una línea de investigación es intentar obtener una idea aproximada de dónde residen los archivos en el disco, y usar eso para secuenciar las lecturas. Sin embargo, no estoy seguro de qué API se podría utilizar para hacer eso.

Por supuesto, estoy abierto a cualquier otra idea.

El sistema de archivos es ext4, pero eso es negociable.


Dado que las operaciones son similares y los datos son independientes, puede intentar usar un grupo de subprocesos para enviar trabajos que funcionen en varios archivos (puede ser un solo archivo). Luego puede hacer que un hilo inactivo complete un solo trabajo. Esto podría ayudar a superponer las operaciones de IO con la ejecución.


Tal vez podría hacer las lecturas programando todas ellas en rápida sucesión con aio_read . Eso pondría todas las lecturas en la cola de lectura del sistema de archivos a la vez, y luego la implementación del sistema de archivos es libre de completar las lecturas de una manera que minimice las búsquedas.


Un enfoque muy simple, aunque no hay resultados garantizados. Abra todos los archivos a la vez que pueda y léalos todos a la vez, ya sea mediante subprocesos o E / S asincrónicas. De esta forma, el planificador de discos sabe lo que lee y puede reducir las búsquedas por sí mismo. Editar: como wildplasser observa, parallel open() probablemente solo sea factible usando hilos, no asincronización de E / S.

La alternativa es intentar hacer el trabajo pesado usted mismo. Desafortunadamente, esto implica un paso difícil: lograr que los archivos se correlacionen con bloques físicos. No hay una interfaz estándar para hacer eso, probablemente podría extraer la lógica de algo como ext2fsprogs o el controlador kernel FS. Y esto implica leer el dispositivo físico subyacente a un sistema de archivos montado, que puede escribir en él al mismo tiempo que intenta obtener una instantánea coherente.

Una vez que obtenga los bloques físicos, solo pídalos, invierta la asignación a los desplazamientos de archivos y ejecute las lecturas en el orden físico de bloques.


Una forma simple sería mantener el programa original, pero incluir un proceso adicional que no tiene otra tarea que la de captación previa de los archivos y preparar el caché del búfer del disco. (Un sistema unix / linux usa toda la memoria "libre" como buffer de disco).

La tarea principal quedará unos pocos archivos atrás (digamos diez). La parte difícil sería mantener las cosas sincronizadas. Una pipa parece la forma obvia de lograr esto.

ACTUALIZAR:

Pseudo código para el proceso principal:

    • recuperar el nombre de archivo de la lista de trabajo
    • si está vacío, vaya a 2.
    • (tal vez) fork un proceso de trabajo o hilo
    • agregar a la cola de captación previa
    • agregar a la cola interna
    • si hay menos de XXX elementos en la cola interna, vaya a 1
    • recuperar el nombre de archivo de la cola interna
    • procesalo
    • goto 1

Para los procesos esclavos:

  • buscar de la cola
  • si está vacío: salga
  • archivo de búsqueda previa
  • bucle o salir

Para la cola, una cola de mensajes parece ser la más adecuada, ya que mantiene los límites del mensaje. Otra forma sería tener una tubería por niño (en el caso de la horquilla ()) o usar mutex (al usar hilos).

Necesitarás hilos / procesos aproximados de seektime_per_file / processing_time_per_file.

Como una simplificación: si no se requiere buscar los archivos (solo acceso secuencial), los procesos esclavos podrían consistir en el equivalente de

dd if=name bs=500K

, que podría envolverse en un popen () o un pipe + fork ().