2011-02-01 22 views
7

Tengo un archivo con "agujeros" y quiero llenarlos con datos; También necesito poder liberar espacio "usado" y liberar espacio.Estructura de datos y algoritmo para representar/asignar espacio libre en un archivo

Estaba pensando en usar un bi-mapa que mapea el desplazamiento y la longitud. Sin embargo, no estoy seguro de si ese es el mejor enfoque si realmente hay pequeñas lagunas en el archivo. Un mapa de bits funcionaría, pero no sé cómo se puede cambiar fácilmente de forma dinámica para ciertas regiones del espacio. ¿Tal vez algún tipo de árbol de raíz es el camino a seguir?

Por lo que vale, estoy a la última en el diseño de sistemas de archivos modernos (ZFS, HFS +, NTFS, XFS, ext ...) y sus soluciones me parecen lamentablemente inadecuadas.

Mis objetivos son ahorrar bastante espacio (de ahí la preocupación por los pequeños fragmentos). Si no me importaba eso, simplemente iría por dos árboles de separación ... Uno ordenado por desplazamiento y el otro ordenado por longitud con vínculos rotos por desplazamiento. Tenga en cuenta que esto le proporciona el registro amortizado (n) para todas las operaciones con un tiempo de ajuste de trabajo de log (m) ... Muy bien ... Pero, como se mencionó anteriormente, no maneja los problemas relacionados con la alta fragmentación.

+0

Hay hay muchos intercambios en el diseño de un sistema de archivos (usted está haciendo la parte de asignación de espacio). Creo que es mejor comenzar a leer sobre ellos, porque las respuestas darán una imagen completa. –

+0

Um, los sistemas de archivos generalmente tienen muy mal representaciones de espacio libre ... –

+0

@Helen Esto se debe a que el sistema de archivos habitual no está ajustado a una aplicación especial. Puede diseñar su política de asignación y representación de acuerdo con sus necesidades. Recuerde comenzar sus comentarios con @nombre de usuario , entonces la otra parte recibe una notificación. –

Respuesta

0

La solución más simple es free list: mantenga una lista vinculada de bloques libres, reutilizando el espacio libre para almacenar la dirección del siguiente bloque en la lista.

+0

Esa es una solución realmente mala en comparación con el uso de un mapa, cada operación es lenta ... –

+0

¿Quiere decir un mapa de listas que tiene como clave el tamaño del tamaño de "agujero" libre? ¿Qué pasa si el agujero que desea no está disponible? Necesitas escanear el resto del árbol por un agujero más grande que tu pedido: eso es O (n). – vz0

+1

Un mapa ordenado por desplazamiento es mejor que esa lista enlazada absurda. Puedo liberar y agregar espacio en el tiempo O (log n) en lugar de tratar de mantener una lista enlazada ordenada.Además, puedo iterar sobre el mapa en tiempo lineal con el espacio O (log n), una compensación fácil de hacer ... –

1

He enviado software comercial que hace precisamente eso. En la última iteración, terminamos ordenando los bloques del archivo en "tipo" e "índice", para que pudiera leer o escribir "el tercer bloque de tipo foo". El archivo terminó estructurado como:

1) Cabecera del archivo. Puntos en la lista de tipos principales. 2) Datos. Cada bloque tiene un encabezado con tipo, índice, tamaño lógico y tamaño acolchado. 3) matrices de (tuplas de compensación, tamaño) para cada tipo dado. 4) Matriz de (tipo, desplazamiento, recuento) que realiza un seguimiento de los tipos.

Lo definimos para que cada bloque sea una unidad atómica. Comenzó a escribir un nuevo bloque, y terminó de escribir eso antes de comenzar cualquier otra cosa. También podría "establecer" el contenido de un bloque. A partir de un nuevo bloque siempre se agrega al final del archivo, para que pueda agregar todo lo que desee sin fragmentar el bloque. "Configurar" un bloque podría reutilizar un bloque vacío.

Al abrir el archivo, cargamos todos los índices en la RAM. Cuando vació o cerró un archivo, volvimos a escribir cada índice que cambió, al final del archivo, luego volvimos a escribir el índice índice al final del archivo, y luego actualizamos el encabezado al frente. Esto significa que los cambios en el archivo fueron todos atómicos: o se compromete al punto donde se actualiza el encabezado, o no. (Algunos sistemas usan dos copias del encabezado de 8 kB para preservar los encabezados, incluso si el sector de un disco sale mal, no lo llevamos tan lejos)

Uno de los "tipos" de bloque era "bloque libre". Al volver a escribir los índices cambiados, y al reemplazar los contenidos de un bloque, el espacio anterior en el disco se fusionó en la lista libre que se guardaba en la matriz de bloques libres. Los bloques libres adyacentes se fusionaron en un solo bloque más grande. Los bloques gratuitos se reutilizaron cuando "establecía el contenido" o para los índices de bloque de tipo actualizados, pero no para el índice del índice, que siempre se escribió al final.

Dado que los índices siempre se conservaron en la memoria, trabajar con un archivo abierto fue realmente rápido, normalmente solo una lectura para obtener los datos de un bloque (o manejar un bloque para la transmisión). La apertura y el cierre fueron un poco más complejos, ya que necesitaban cargar y eliminar los índices. Si se convierte en un problema, podemos cargar el índice de tipo secundario a pedido en lugar de hacerlo por adelantado para amortizar ese costo, pero nunca fue un problema para nosotros.

Prioridad máxima para el almacenamiento persistente (en disco): ¡Robustez! ¡No pierda datos incluso si la computadora pierde potencia mientras trabaja con el archivo! Segunda prioridad para el almacenamiento en disco: ¡No haga más E/S de lo necesario! Las búsquedas son costosas. En unidades Flash, cada E/S individual es costosa, y las escrituras lo son doblemente. Intenta alinear y procesar por lotes I/O. Usar algo como malloc() para el almacenamiento en disco generalmente no es genial, porque hace demasiadas búsquedas. Esta es también una razón por la que no me gustan mucho los archivos mapeados en memoria: las personas tienden a tratarlos como RAM, y luego el patrón de E/S se vuelve muy costoso.

1

Para la gestión de la memoria, soy un entusiasta del enfoque BiBOP *, que normalmente es eficiente en la gestión de la fragmentación.

La idea es segregar los datos en función de su tamaño. Esto, manera, dentro de una "bolsa" es suficiente "páginas" de pequeños bloques con tamaños idénticos:

  • hay necesidad de almacenar el tamaño de forma explícita, se sabe dependiendo de la bolsa que está en
  • sin fragmentación "real" dentro de una bolsa

La bolsa contiene una simple lista de las páginas disponibles. Cada página mantiene una lista libre de unidades de almacenamiento disponibles en una superposición sobre esas unidades.

Necesita un índice para asignar el tamaño al bolso correspondiente.

También necesita un tratamiento especial para solicitudes "fuera de norma" (es decir, solicitudes que solicitan una asignación mayor que el tamaño de página).


Este almacenamiento es extremadamente eficiente del espacio, especialmente para objetos pequeños, debido a la sobrecarga no es per-objeto, sin embargo, hay un inconveniente: puede terminar arriba con las páginas de "casi vacío" que todavía contienen uno o dos unidades de almacenamiento ocupadas.

Esto se puede aliviar si tiene la capacidad de "mover" los objetos existentes. Lo que efectivamente permite combinar páginas.

(*) Bibop: Big Bag de Páginas

1

Recomendaría hacer archivo-sistema personalizado (que podría contener un archivo, por supuesto), con base en FUSE. Hay a lot of available solutions for FUSE en los que puede basarse: recomiendo elegir proyectos no relacionados pero más simples, para aprender fácilmente.

Lo que el algoritmo y la estructura de datos para elegir, se profundiza mucho en sus necesidades. Puede ser: mapa, lista o archivo dividido en fragmentos con compresión/descompresión sobre la marcha.

Las estructuras de datos propuestas por usted son buenas ideas. Como puede ver claramente, hay una compensación: fragmentación vs compactación.

Por un lado, la mejor compactación, la fragmentación más alta y muchos otros tipos de árboles.

Por otro lado, la fragmentación más baja, la peor lista vinculada a la compactación.

En el medio hay B-Trees y otros.

Según tengo entendido, usted indicó como prioridad: ahorro de espacio, mientras se ocupa del rendimiento.

Recomendaría su estructura de datos mixtos para cumplir todos los requisitos.

  • una especie de lista de bloques contiguos de datos
  • una especie de árbol para la corriente "añadir/quitar" operación
  • cuando se requieren datos sobre la demanda, asignar del árbol. Cuando se elimine, realice un seguimiento de lo que se "borra" usando también árbol.
  • mixing -> durante cada operación (o en momentos de inactividad) realice la des-fragmentación "paso a paso", y aplique los cambios guardados en el árbol en bloques contiguos, mientras los mueve lentamente.

Esta solución le da una rápida respuesta de la demanda, mientras que "optimización" cosas mientras se utiliza, (Por ejemplo, "cada lectura de 10 MB de datos -> defragmantation de 1 MB). O en momentos de ocio

Cuestiones relacionadas