¿Por qué mi función “gato” con llamadas al sistema más lento en comparación con el “gato” de Linux?

StackOverflow https://stackoverflow.com/questions/769550

  •  12-09-2019
  •  | 
  •  

Pregunta

He hecho esta función en C usando las llamadas al sistema (abierto, leer y escribir) para simular la función de "gato" en los sistemas Linux y es más lento que la real ...

Estoy utilizando el mismo tamaño de búfer como el "gato" real y el uso de "strace" Creo que se trata de hacer la misma cantidad de llamadas al sistema. Pero la salida de mi "gato" es un poco más lento que el verdadero "gato".

Este es el código que tengo:

#define BUFSIZ 32768

int sysWriteBuffer(int fdout, char *buffer, ssize_t readBytes) {
    ssize_t writtenBytes = 0;

    while(writtenBytes < readBytes) {
        writtenBytes += write(fdout,
            buffer + writtenBytes, readBytes - writtenBytes);
        if(writtenBytes == -1) {
            return -1;
        }
    }

    return 0;
}

int catPrint(int fdin, int fdout) {
    char buffer[BUFSIZ];
    ssize_t readBytes;

    do {
        readBytes = read(fdin, buffer, BUFSIZ);

        if(readBytes == -1) {
            return -1;
        }

        if(sysWriteBuffer(fdout, buffer, readBytes) == -1) {
            return -1;
        }
    } while(readBytes > 0);

    return 0;
}

Estoy leyendo desde un archivo (que me pase como argumento al principal, creo que el código no es necesario aquí) lo que yo llamo la función catPrint () con el descriptor de archivo y 1 para el descriptor de salida por lo que imprime a stdout.

No entiendo por qué es más lento porque estoy usando el mismo archivo para la prueba y con ambos (el verdadero "gato" y la mía) sólo hay una lectura () y uno de escritura () para todo el texto. En caso de que no todo el texto que acaba de aparecer en la pantalla?

P.S: Me ha etiquetado esto como tarea aunque mi pregunta aquí (por eso que es más lento) no es parte de la tarea. Yo sólo tenía que utilizar el sistema llama a crear una función de tipo "gato", que se realiza. Estoy intrigado por mi código que es un poco más lento.

problema resuelto con la estupidez DE ME:
Decidí llamar gato original del linux unas cuantas veces en el mismo archivo, uno tras otro, y me he dado cuenta de que también era lento algunas de las veces que me llamaron, simplemente tan lento como la mía. Supongo que todo está bien ...

Lo siento por perder su tiempo como este pueblo.

¿Fue útil?

Solución

Ah, basado en su edición que estaban siendo mordido por el buffer de lectura anticipada. No se puede probar dos programas que leen archivos en paralelo mediante la ejecución de una vez. La primera siempre será más lenta ya que el archivo está en el disco, una vez que el archivo está en la memoria la segunda funcionará más rápido, se debe crear nuevos datos para cada una o ejecutar uno y luego ejecutar tanto por lo que ambos obtienen el beneficio de la memoria intermedia de lectura anticipada.

Otros consejos

Investigación mmap (2).

Va a ser tirar aways sutilezas de ftell / fread, pero se salta una capa de direccionamiento indirecto si el rendimiento de leer es muy importante.

Tal vez se ha compilado sin optimización (o sin tan alto un ajuste de optimización)?

Además, su código llamará sysWriteBuffer una vez con readBytes igual a cero - tal vez que (parcialmente) lo explica

?

También puede inline sysWriteBuffer (ya sea a través de un modificador de compilador o con la mano).

"inline" significa copiar el cuerpo de una función llamada a su sitio con el fin para eliminar la sobrecarga de llamar a una función. A veces compiladores lo hacen automáticamente (creo -O3 permite esta optimización de gcc). También puede utilizar la palabra clave de la inline en gcc para contar el compilador para una función inline. Si se hace esto, su declaración se parecerá a esto:

static inline int sysWriteBuffer(int fdout, char *buffer, ssize_t readBytes) {
....

Sin comparar los códigos fuente, es difícil de decir. Si está comparando su gato con el gato de GNU, recuerde que usted está comparando un código que se encuentra a pocos horas / días de edad con un código que se desarrolló durante más de veinte años.

Es posible que desee hacer un análisis más exhaustivo de rendimiento, la ejecución de los programas de ambos con diferentes tamaños de entrada, desde diferentes dispositivos (un disco RAM sería bueno) y varias veces en una fila. Usted debe tratar de determinar en qué parte de su programa es más lento.

Desde gato en sí es muy trivial (y que ha dicho en un comentario que ya está optimizando la compilación), apuesto a que el impacto en el rendimiento que se está observando no está en el algoritmo real, pero en los tiempos de carga del programa. Si el sistema binario es preenlazada (que es común en la mayoría de distribuciones de hoy en día), se verá que se carga más rápido que cualquier programa se compila a sí mismo (hasta que incluir sus programas prelinkado).

¿Cuánto? El gato canónica es algo así como

char bufr[BUFSIZ];
ssize_t len;

while((len=read(fdin, bufr, BUFSIZ)) >0)
     write(fdout, bufr, len);

lo que ahorra unas pocas instrucciones.

¿Ha comparado straces de ambos? Usted puede tratar de utilizar el parámetro -tt para que pueda obtener el tiempo de las llamadas al sistema.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top