Por que ler () é mais lento que getc ()? [fechadas]

2

Por que read é mais lento que getc ?

Por exemplo, isso:

for (;;) {
        chr++;
        amr=read(file1, &wc1, 1);
        amr2=read(file2, &wc2, 1);
        if (wc1 == wc2) {
            if (wc1 == '\n')
                line++;
            if (amr == 0) {
                if (eflg)
                    return (1);
                return (0);
            }
            continue;
        }

é mais lento que isso:

for (;;) {
    chr++;
    c1 = getc(file1);
    c2 = getc(file2);
    if (c1 == c2) {
        if (c1 == '\n')
            line++;
        if (c1 == EOF) {
            if (eflg)
                return (1);
            return (0);
        }
        continue;
    }

getc usa a chamada do sistema read , então por que é mais lento?

    
por Alex Zern 22.04.2013 / 13:15

2 respostas

11

Como getc () armazena em buffer os dados lidos antes de retorná-los, portanto, uma chamada para getc() não resulta necessariamente em uma chamada para read() . read() é uma chamada de sistema, que leva muito mais tempo para ser realizada do que uma chamada de função normal, porque o kernel tem mais operações para fazer. Quando você entra no espaço do kernel, ele muda sua pilha, salva todo o contexto, lida com as interrupções para mascarar, e no outro lado, quando terminar, restaura o contexto, as interrupções, recoloca sua pilha de espaço do usuário. É por isso que getc () é o preferido porque poupa uma sobrecarga importante se você já tiver dados em buffer disponíveis.

    
por 22.04.2013 / 13:20
3

Tudo se resume ao fato de que leituras de discos são orientadas a blocos: para ler um único byte de um disco, o hardware acaba lendo um bloco (512 ou 1024 ou algum número) de bytes, armazenando tudo isso, passando-o para o kernel. Se você ler o byte 0 do arquivo do bloco 0 do arquivo, fazer algum trabalho e, em seguida, ler o byte 1 do arquivo, o kernel provavelmente acabará lendo no bloco 0 do arquivo novamente. E novamente para o byte 2 e novamente para o byte 3. Sim, há um potencial cache, tanto no kernel quanto na própria unidade de disco, mas o kernel lida com muitos processos, então talvez não.

Cada chamada read() também tem que mudar a CPU do estado do usuário para o estado do kernel. Os mapeamentos de memória mudam, no mínimo. Provavelmente muitas outras coisas não tão óbvias acontecem. Isso pode levar tempo também.

Uma chamada de sistema read() altera o estado da CPU e pode implicar E / S de disco. getc() pode armazenar em buffer um bloco de disco inteiro (ou mais) no espaço do usuário, então talvez 512 chamadas para getc() façam com que o kernel leia em um único bloco de disco, com uma única mudança de estado. Se você olhar em stdio.h , encontrará uma macro para uma constante BUFSIZ , que deve ser um tamanho eficiente (disco-bloco múltiplo) para uma chamada de sistema read() ou write() para um arquivo no disco .

    
por 22.04.2013 / 15:46

Tags