2012-04-25 17 views
8

Estoy utilizando la función llamada fwrite() para escribir datos en un conducto en Linux.Entender el comportamiento de búfer de fwrite()

Anteriormente, se llamaba a fwrite() en busca de pequeños fragmentos de datos (promedio de 20 bytes) repetidamente y el almacenamiento en búfer se había dejado en fwrite(). El proceso demostró que se estaban escribiendo 4096 bytes de datos a la vez.

Resultó que este proceso de escritura fue el cuello de botella en mi programa. Así que decidí almacenar datos en mi código en bloques de 64 KB y luego escribir todo el bloque a la vez usando fwrite(). Usé setvbuf() para configurar el puntero ARCHIVO * en 'Sin almacenamiento en búfer'.

La mejora en el rendimiento no fue tan significativa como esperaba.

Más importante aún, la salida strace mostró que aún se estaban escribiendo datos de 4096 bytes a la vez. ¿Puede alguien explicarme este comportamiento? Si llamo al fwrite() con 64 KB de datos, ¿por qué está escribiendo solo 4096 bytes a la vez?

¿Hay una alternativa a fwrite() para escribir datos en una tubería utilizando un puntero FILE *?

+0

¿Puede mostrarnos el código? – tuxuday

+1

@Shailesh_Tainwala: Es posible que esté escribiendo su código en C++, pero esta es una pregunta c en lugar de C++. 'fwrite()' es una función c, no una función C++. Agregué una etiqueta c a su pregunta para que pueda obtener una audiencia más amplia. –

Respuesta

8

La 4096 proviene de la maquinaria Linux que subyace a las tuberías. Hay dos lugares donde ocurre. Una es la capacidad de la tubería. La capacidad es una página del sistema en versiones anteriores de Linux, que es 4096 bytes en una máquina i386 de 32 bits. (En versiones más modernas de Linux, la capacidad es de 64 K.)

El otro lugar donde se encontrará con ese problema de 4096 bytes es en la constante definida PIPE_BUF, la cantidad de bytes que se garantiza que se tratarán atómicamente. En Linux esto es 4096 bytes. Lo que este límite significa depende de si ha configurado la interconexión como bloqueante o no bloqueante. Haz un man -S7 pipe para todos los detalles sangrientos.

Si está tratando de intercambiar grandes volúmenes de datos a gran velocidad, es posible que desee replantearse el uso de las tuberías. Estás en una caja de Linux, por lo que la memoria compartida es una opción. Puede usar tuberías para enviar cantidades relativamente pequeñas de datos como un mecanismo de señalización.

+0

Otra opción posible de Linux sería usar open() y splice() en lugar de fwrite(). –

4

Si desea cambiar el comportamiento de amortiguación, debe hacerlo inmediatamente después de la fopen (o antes de cualquier E/S, para los controladores de archivo estándar stdin, stdout, stderr). Tampoco desea deshabilitar el almacenamiento en búfer e intentar administrar el búfer usted mismo; más bien, especifique su memoria intermedia de 64 KB en setvbuf para que pueda usarse correctamente.

Si realmente desea administrar el almacenamiento en búfer manualmente, no use stdio; utilice las llamadas de nivel inferior open, write y close.

Cuestiones relacionadas