overloaded - monitoring disk io linux
Linux: cuándo usar dispersión/recopilar E/S(readv, writev) frente a un gran búfer con fread (1)
La conveniencia principal ofrecida por readv
, writev
es:
- Permite trabajar con bloques de datos no contiguos. es decir, los buffers no tienen que formar parte de una matriz, sino que deben asignarse por separado.
- La E / S es ''atómica''. es decir, si realiza una
writev
, todos los elementos del vector se escribirán en una operación contigua, y las escrituras realizadas por otros procesos no se producirán entre ellas.
Por ejemplo, digamos que sus datos están segmentados naturalmente y provienen de diferentes fuentes:
struct foo *my_foo;
struct bar *my_bar;
struct baz *my_baz;
my_foo = get_my_foo();
my_bar = get_my_bar();
my_baz = get_my_baz();
Ahora, los tres ''buffers'' no son un gran bloque contiguo. Pero desea escribirlos contiguamente en un archivo, por cualquier motivo (por ejemplo, son campos en el encabezado de un archivo para un formato de archivo).
Si usas write
tienes que elegir entre:
- Copiándolos en un bloque de memoria usando, por ejemplo,
memcpy
(sobrecarga), seguido de una sola llamada dewrite
. Entonces la escritura será atómica. - Hacer tres llamadas separadas para
write
(gastos generales). Además, las llamadas dewrite
de otros procesos pueden intercalarse entre estas escrituras (no atómicas).
Si usas writev
en su lugar, todo está bien:
- Usted hace exactamente una llamada al sistema, y no hay
memcpy
para hacer un solo búfer de los tres. - Además, los tres búferes se escriben atómicamente, como escritura de un bloque. es decir, si otros procesos también escriben, entonces estas escrituras no aparecerán entre las escrituras de los tres vectores.
Entonces harías algo como:
struct iovec iov[3];
iov[0].iov_base = my_foo;
iov[0].iov_len = sizeof (struct foo);
iov[1].iov_base = my_bar;
iov[1].iov_len = sizeof (struct bar);
iov[2].iov_base = my_baz;
iov[2].iov_len = sizeof (struct baz);
bytes_written = writev (fd, iov, 3);
Fuentes:
En dispersión y recopilación (es decir, readv
y writev
), Linux lee en múltiples buffers y escribe desde múltiples buffers.
Por ejemplo, si tengo un vector de 3 buffers, puedo usar readv
, O puedo usar un solo buffer, que es de un tamaño combinado de 3 buffers y hago fread
.
Por lo tanto, estoy confundido: ¿para qué casos se debe utilizar la dispersión / recopilación y cuándo se debe usar un solo búfer grande?