2012-03-12 24 views
12

Estoy usando la función de escritura de I/O de bajo nivel para escribir algunos datos en el disco en mi código (lenguaje C en Linux). Primero, acumulo los datos en un buffer de memoria, y luego uso 'write' para escribir los datos en el disco cuando el buffer está lleno. Entonces, ¿cuál es el mejor tamaño de buffer para 'escribir'? Según mis pruebas, no es tanto más grande cuanto más rápido, así que estoy aquí para buscar la respuesta.¿cuál es el tamaño de búfer adecuado para la función 'escribir'?

+0

+1 para hacer una buena pregunta ... Siempre quise saber el tamaño correcto para la función de escritura .... – aProgrammer

+0

posible duplicado de [Tamaño óptimo de la memoria intermedia para escritura (2)] (http://stackoverflow.com/questions/8803515/optimum-buffer-size-for-write2) – Raedwald

Respuesta

3

Probablemente haya alguna ventaja al hacer escrituras que son múltiplos del tamaño del bloque del sistema de archivos, especialmente si está actualizando un archivo en su lugar. Si escribe menos de un bloque parcial en un archivo, el sistema operativo debe leer el bloque antiguo, combinarlo en los nuevos contenidos y luego escribirlo. Esto no ocurre necesariamente si escribe rápidamente piezas pequeñas en secuencia porque las actualizaciones se realizarán en memorias intermedias en la memoria que se enjuagarán más tarde. Aún así, de vez en cuando podría estar desencadenando alguna ineficacia si no está llenando un bloque (y uno correctamente alineado: múltiples del tamaño del bloque en un desplazamiento que es un múltiplo del tamaño del bloque) con cada operación de escritura.

Este problema de tamaño de transferencia no necesariamente desaparece con mmap. Si mapea un archivo, y luego memcpy algunos datos en el mapa, está ensuciando una página. Esa página debe ser eliminada en algún momento posterior: es indeterminada cuando. Si crea otro memcpy que toque la misma página, esa página podría estar limpia ahora y la volverá a ensuciar. Entonces se escribe dos veces. El camino a seguir consiste en copias alineadas en la página de múltiplos de un tamaño de página.

3

Lo querrás que sea un múltiplo del tamaño de página de la CPU, para poder usar la memoria de la manera más eficiente posible.

Pero lo ideal es utilizar mmap en su lugar, para que nunca tenga que ocuparse de los búferes.

+0

+1 para usar mmap –

+0

Entonces, si quiere escribir 3GB de datos, ¿está bien hacer un mmap de 3GB? Jaja. Puede hacer un mmap más pequeño y luego reasignarlo mientras avanza por el archivo, lo cual es más complicado. En cuanto a ningún buffers: bueno, ¿qué es el mmap? Es una región de memoria con un puntero base y un puntero actual que te dice dónde memcpy la siguiente pieza. ¿Y cuál es el tamaño ideal para esas operaciones memcpy? Si copia 300 bytes aquí, 300 bytes allí, podría desencadenar descargas subóptimas. Es decir. la CPU podría atraparte haciendo que la misma página se ensucie dos veces y que se vacíe dos veces. – Kaz

+0

¿Qué pasa si los datos a procesar son mucho más grandes que la RAM? –

1

Depende de la cantidad de RAM, VM, etc., así como de la cantidad de datos que se escriben. La respuesta más general es comparar qué buffer funciona mejor para la carga con la que está trabajando y usar lo que funciona mejor.

+1

¿cuál es una buena forma de calcular la cantidad adecuada dada toda esto – pyCthon

+0

iterar a través de las diferentes configuraciones para tamaños de búfer y compararlo? –

+0

que funciona, supongo que me preguntaba si había algún tipo de fórmula basada en ram, vm exc – pyCthon

3

usted podría utilizar BUFSIZ definido en <stdio.h>

lo contrario, utilice un pequeño múltiplo del tamaño de página sysconf(_SC_PAGESIZE) (por ejemplo dos veces ese valor). La mayoría de los sistemas Linux tienen páginas de 4Kbytes (que a menudo es el mismo o un pequeño múltiplo del tamaño del bloque del sistema de archivos).

Como otros respondieron, usar el sistema mmap(2) podría ayudar. Los sistemas GNU (por ejemplo, Linux) tienen una extensión: la cadena del segundo modo de fopen puede contener la última m y cuando eso sucede, la libc de GNU intenta mmap.

Si maneja datos tan grandes como su RAM (o la mitad de ella), también puede usar madvise(2) para ajustar el rendimiento de mmap.

Consulte también this answer para una pregunta bastante similar a la suya. (Podría usar 64Kbytes como un tamaño de búfer razonable).

2

El "mejor" tamaño depende en gran medida del sistema de archivos subyacente.

Los stat y fstat llamadas llenan en una estructura de datos, struct stat, que incluye el siguiente campo:

blksize_t st_blksize; /* blocksize for file system I/O */ 

El sistema operativo es responsable de llenar este campo con un "buen tamaño" para escribir() bloquea.Sin embargo, también es importante llamar a write() con la memoria que está "bien alineada" (por ejemplo, el resultado de las llamadas malloc). La forma más fácil de conseguir que esto suceda es utilizar la interfaz de secuencia <stdio.h> proporcionada (con objetos FILE *).

El uso de mmap, como en otras respuestas aquí, también puede ser muy rápido en muchos casos. Sin embargo, tenga en cuenta que no es adecuado para algunos tipos de transmisiones (por ejemplo, tomas de corriente y tuberías).

+0

¿quiere decir que fwrite es generalmente más rápido que escribir con un tamaño de búfer adecuado? –

+0

No necesariamente "más rápido que", pero sí bloqueará rápidamente las copias en el espacio de usuario según sea necesario. Además, si necesita escribir un conjunto de cadenas cortas diferentes desde varias ubicaciones, las reunirá todas juntas y pasará un bloque de tamaño apropiado al kernel, en una llamada al sistema. (Puede lograr un efecto similar con 'writev' en algunos casos, pero generalmente es más trabajo de lo que vale, e incluso entonces el kernel tiende a tener que hacer las mismas copias de memoria). – torek

+0

Este valor pretende ser exactamente eso, pero resultó que si uso este valor, aún es más lento si, por ejemplo copiando datos de A a B, porque tengo que hacer más llamadas de sistema de esta manera. – glglgl

Cuestiones relacionadas