¿Qué tan eficiente es cat(1)?

Ha habido algunas iniciativas en los últimos años para implementar un nuevo sistema de espacio de usuario básico para las distribuciones de Linux como alternativa a GNU y BusyBox coreutils. Recientemente, uno de los autores de una de estas implementaciones propuestas argumentó en algunos canales de IRC que su implementación cat, que se derivaba de la implementación de OpenBSD, era la más eficiente. ¿Pero es realmente?

Entiende lo que el gato realmente hace

En el nivel más básico, cat toma uno o más archivos y los vuelca en la salida estándar. Pero, ¿realmente necesitamos usar stdio para eso? De hecho, no lo hacemos, y la mayoría de las implementaciones cat competentes utilizan al menos enfoques de lectura (2) y escritura (2), si no más avanzados.

Si consideramos a cat como una forma de copia de búfer entre un descriptor de archivo arbitrario y STDOUT_FILENO, podemos entender cuál sería la estrategia más eficiente para cat: el empalme. Después de todo, cualquier cosa que no empalme implica copias de búfer innecesarias y, por lo tanto, no puede ser lo más eficiente.

Para obtener el mejor rendimiento de las E/S empalmadas, debemos cumplir algunos requisitos previos:

Los descriptores de archivo de origen y de destino deben estar sin búfer. Cualquier búfer intermedio debe ser un múltiplo del tamaño del bloque del sistema de archivos. En general, para evitar realizar una llamada al sistema estadístico, podemos suponer que probablemente sea aceptable un múltiplo de PAGE_SIZE. Una implementación de chat simple

La forma más fácil de implementar cat es la forma en que se hace en BSD: usando lectura y escritura en un búfer intermedio. Esto da como resultado dos copias almacenadas en búfer, pero proporciona la mejor portabilidad. La mayoría de las implementaciones de cat funcionan de esta manera, ya que suelen proporcionar un rendimiento suficiente.

/* Este programa es de dominio público. */ #comprender #comprender #comprender #comprender #comprender #comprender #comprender void dumpfile(const char *ruta) { int srcfd = STDIN_FILENO; char buf[TAMAÑO_PÁGINA * 16]; tamaño_t nlu, newrite; desplazamiento de tamaño_t; /* POSIX permite - representar stdin. */ si (*ruta!= '-') { srcfd = open(ruta, O_RDONLY); si (srcfd < 0) err(EXIT_FAILURE, "abrir %s", ruta); } while ((nread = read(srcfd, buf, tamaño de buf)) >= 1) { for (offset = 0; nread > 0; nread -= no escrito, offset += no escrito) { if ((nwrite = write(STDOUT_FILENO, buf + offset, nread)) 0); devolver verdadero; } cancelar copia (int srcfd) { char buf[TAMAÑO_PÁGINA * 16]; tamaño_t nlu, newrite, desplazamiento; while ((nread = read(srcfd, buf, tamaño de buf)) >= 1) { para (desplazamiento = 0; nleer > 0; nlu -= no escrito, offset += no escrito) { if ((nwrite = write(STDOUT_FILENO, buf + shift, nread))

¿Qué tan eficiente es cat(1)?

Ha habido algunas iniciativas en los últimos años para implementar un nuevo sistema de espacio de usuario básico para las distribuciones de Linux como alternativa a GNU y BusyBox coreutils. Recientemente, uno de los autores de una de estas implementaciones propuestas argumentó en algunos canales de IRC que su implementación cat, que se derivaba de la implementación de OpenBSD, era la más eficiente. ¿Pero es realmente?

Entiende lo que el gato realmente hace

En el nivel más básico, cat toma uno o más archivos y los vuelca en la salida estándar. Pero, ¿realmente necesitamos usar stdio para eso? De hecho, no lo hacemos, y la mayoría de las implementaciones cat competentes utilizan al menos enfoques de lectura (2) y escritura (2), si no más avanzados.

Si consideramos a cat como una forma de copia de búfer entre un descriptor de archivo arbitrario y STDOUT_FILENO, podemos entender cuál sería la estrategia más eficiente para cat: el empalme. Después de todo, cualquier cosa que no empalme implica copias de búfer innecesarias y, por lo tanto, no puede ser lo más eficiente.

Para obtener el mejor rendimiento de las E/S empalmadas, debemos cumplir algunos requisitos previos:

Los descriptores de archivo de origen y de destino deben estar sin búfer. Cualquier búfer intermedio debe ser un múltiplo del tamaño del bloque del sistema de archivos. En general, para evitar realizar una llamada al sistema estadístico, podemos suponer que probablemente sea aceptable un múltiplo de PAGE_SIZE. Una implementación de chat simple

La forma más fácil de implementar cat es la forma en que se hace en BSD: usando lectura y escritura en un búfer intermedio. Esto da como resultado dos copias almacenadas en búfer, pero proporciona la mejor portabilidad. La mayoría de las implementaciones de cat funcionan de esta manera, ya que suelen proporcionar un rendimiento suficiente.

/* Este programa es de dominio público. */ #comprender #comprender #comprender #comprender #comprender #comprender #comprender void dumpfile(const char *ruta) { int srcfd = STDIN_FILENO; char buf[TAMAÑO_PÁGINA * 16]; tamaño_t nlu, newrite; desplazamiento de tamaño_t; /* POSIX permite - representar stdin. */ si (*ruta!= '-') { srcfd = open(ruta, O_RDONLY); si (srcfd < 0) err(EXIT_FAILURE, "abrir %s", ruta); } while ((nread = read(srcfd, buf, tamaño de buf)) >= 1) { for (offset = 0; nread > 0; nread -= no escrito, offset += no escrito) { if ((nwrite = write(STDOUT_FILENO, buf + offset, nread)) 0); devolver verdadero; } cancelar copia (int srcfd) { char buf[TAMAÑO_PÁGINA * 16]; tamaño_t nlu, newrite, desplazamiento; while ((nread = read(srcfd, buf, tamaño de buf)) >= 1) { para (desplazamiento = 0; nleer > 0; nlu -= no escrito, offset += no escrito) { if ((nwrite = write(STDOUT_FILENO, buf + shift, nread))

What's Your Reaction?

like

dislike

love

funny

angry

sad

wow