language-agnostic io buffering

language agnostic - Buffer versus IO sin búfer



language-agnostic buffering (2)

Aprendí que, por defecto, las E / S en los programas están almacenadas temporalmente, es decir, se sirven desde un almacenamiento temporal al programa solicitante. Entiendo que el almacenamiento en búfer mejora el rendimiento de IO (quizás reduciendo las llamadas al sistema). He visto ejemplos de deshabilitar el almacenamiento en búfer, como setvbuf en C. ¿Cuál es la diferencia entre los dos modos y cuándo se debe usar uno sobre el otro?


Desea salida sin búfer cada vez que desee asegurarse de que la salida se haya escrito antes de continuar. Un ejemplo es el error estándar en una biblioteca de tiempo de ejecución de C; por lo general, esto no está almacenado de forma predeterminada. Dado que los errores son (afortunadamente) poco frecuentes, usted quiere saber sobre ellos de inmediato. Por otro lado, la salida estándar se amortigua simplemente porque se supone que habrá muchos más datos que la atraviesen.

Otro ejemplo es una biblioteca de registro. Si sus mensajes de registro se mantienen dentro de los almacenamientos intermedios en su proceso y su proceso se volca, es muy probable que la salida nunca se escriba.

Además, no solo se minimizan las llamadas al sistema, sino también las E / S del disco. Digamos que un programa lee un archivo de un byte a la vez. Con la entrada sin búfer, saldrá al disco (relativamente muy lento) para cada byte, aunque probablemente tenga que leer en un bloque completo de todos modos (el hardware del disco en sí mismo puede tener almacenamientos intermedios pero todavía está saliendo al controlador del disco) que va a ser más lento que el acceso en memoria).

Mediante el almacenamiento en búfer, se lee todo el bloque en el búfer de una vez, luego se le entregan los bytes individuales desde el área del búfer (en memoria, increíblemente rápida).

Tenga en cuenta que el almacenamiento en búfer puede tomar muchas formas, como en el siguiente ejemplo:

+-------------------+-------------------+ | Process A | Process B | +-------------------+-------------------+ | C runtime library | C runtime library | C RTL buffers +-------------------+-------------------+ | OS caches | Operating system buffers +---------------------------------------+ | Disk controller hardware cache | Disk hardware buffers +---------------------------------------+ | Disk | +---------------------------------------+


Desea salida sin búfer cuando ya tiene una gran secuencia de bytes listos para escribir en el disco, y desea evitar una copia adicional en un segundo búfer en el medio.

Las secuencias de salida almacenadas en búfer acumularán los resultados de escritura en un búfer intermedio, enviándolo al sistema de archivos del sistema operativo solo cuando se hayan acumulado suficientes datos (o se solicite el flush() ). Esto reduce la cantidad de llamadas al sistema de archivos. Dado que las llamadas al sistema de archivos pueden ser costosas en la mayoría de las plataformas (en comparación con memcpy corto), la salida en búfer es una ganancia neta cuando se realiza una gran cantidad de pequeñas escrituras. La salida sin búfer generalmente es mejor cuando ya tiene búferes grandes para enviar; copiar en un búfer intermedio no reducirá el número de llamadas al sistema operativo e introduce trabajo adicional.

La salida sin búfer no tiene nada que ver con garantizar que sus datos lleguen al disco; esa funcionalidad es provista por flush() , y funciona en streams almacenados y no almacenados. Las grabaciones IO sin búfer no garantizan que los datos hayan llegado al disco físico: el sistema de archivos del sistema operativo puede retener indefinidamente una copia de sus datos, nunca escribirlos en el disco, si así lo desea. Solo es necesario enviarlo al disco cuando invocas flush() . (Tenga en cuenta que close() llamará a flush() en su nombre).