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'?
Respuesta
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.
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.
+1 para usar mmap –
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
¿Qué pasa si los datos a procesar son mucho más grandes que la RAM? –
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.
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).
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).
¿quiere decir que fwrite es generalmente más rápido que escribir con un tamaño de búfer adecuado? –
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
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
- 1. ¿Cuál es el tamaño del búfer en BufferedReader?
- 2. C# FileStream: Tamaño de búfer óptimo para escribir archivos grandes?
- 3. ¿Cuál es un buen tamaño de búfer para la programación de socket?
- 4. ¿Cuál es el método adecuado para imprimir excepciones de Python?
- 5. ¿Cuál es el tamaño del búfer para crear un archivo .zip usando Java?
- 6. ¿Cuál es el tamaño de búfer predeterminado para java.io.BufferedInputStream en JVM antiguas y exóticas?
- 7. ¿Es OCaml adecuado para escribir servidores de redes?
- 8. ¿Cuál es el diseño adecuado para hacer frente a esto?
- 9. ¿Cómo escribir el método de descripción adecuado para una clase?
- 10. Elección de un tamaño de tabla adecuado para un hash
- 11. ¿Cuál es el método preferido para escribir "guardias"?
- 12. ¿MapReduce es adecuado para mí?
- 13. ¿Cuál es el __proto__ de la función?
- 14. contribución de Struct para escribir el tamaño
- 15. ¿Cuál es el proceso adecuado para la solicitud/respuesta de eco ICMP en destinos inalcanzables?
- 16. Tanto el zócalo como el archivo recomiendan tamaño de búfer
- 17. ¿Cuál es el patrón de Lua adecuado para el texto entre comillas?
- 18. ¿Cuál es más adecuado para Windows, git o mercurial?
- 19. ¿Cuál es la forma canónica de escribir una función hasher para TEqualityComparer.Construct?
- 20. Cuál es el código de respuesta HTTP adecuado para la solicitud sin campos obligatorios
- 21. ¿Cuál es el tamaño máximo de los metadatos JPEG?
- 22. ¿Cuál es la forma adecuada de escribir con fuerza el retorno de una función genérica?
- 23. Cuál es el tamaño de booleano GLSL
- 24. ¿Cuál es el tamaño aceptable de ViewState
- 25. ¿Cuál es el tamaño de lote recomendado para SqlBulkCopy?
- 26. Cuál es el tamaño máximo de un Node.js Buffer
- 27. ¿Cuál es el tamaño máximo de Web.config?
- 28. ¿Cuál es el "modo Rails" adecuado para consumir un servicio web RESTful en otro dominio?
- 29. Establecer tamaño de búfer de tubería
- 30. ¿Cuál es el tamaño óptimo para una aplicación de Android?
+1 para hacer una buena pregunta ... Siempre quise saber el tamaño correcto para la función de escritura .... – aProgrammer
posible duplicado de [Tamaño óptimo de la memoria intermedia para escritura (2)] (http://stackoverflow.com/questions/8803515/optimum-buffer-size-for-write2) – Raedwald