Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

Why is read slower than getc?

For example, this:

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;
        }

is slower than that:

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 uses the read system call, so why is it slower?

share|improve this question

closed as off topic by Renan, manatwork, vonbrand, jasonwryan, uther Apr 22 '13 at 19:12

Questions on Unix & Linux Stack Exchange are expected to relate to Unix or Linux within the scope defined by the community. Consider editing the question or leaving comments for improvement if you believe the question can be reworded to fit within the scope. Read more about reopening questions here.If this question can be reworded to fit the rules in the help center, please edit the question.

4  
Because getc is buffered operation. It read data from disk once into a buffer, after that it reads symbols from memory. –  Eddy_Em Apr 22 '13 at 11:18
    
Please stop posting programming questions here; if you're question-banned on Stack Overflow, see meta.stackexchange.com/questions/86997/… –  Michael Mrozek Apr 22 '13 at 19:23

2 Answers 2

Because getc() buffers the read data before returning it, so a call to getc() does not necessarily result in a call to read(). read() is a system call, which takes much longer time to accomplish than a normal function call because the kernel has more operations to do. When you enter the kernel space, it changes your stack, saves all the context, deals with the interruptions to mask, and at the other end, when it has finished, it restores the context, the interruptions, put your userspace stack back... That's why getc() is preferred because it saves you an important overhead if you already have available buffered data.

share|improve this answer

It comes down to the fact that reads from disks are block oriented: to read a single byte from a disk, the hardware ends up reading a block (512 or 1024 or some number) of bytes, buffering all that, passing it to the kernel. If you read byte 0 of the file from block 0 of the file, do some work, then read byte 1 from the file, the kernel probably ends up reading in block 0 of the file again. And again for byte 2, and again for byte 3. Yes, there's potential caching, both in the kernel and in the disk drive itself, but the kernel handles a lot of processes, so maybe not.

Each read() call also has to change the CPU from user state to kernel state. Memory mappings change, at the very least. Probably a lot of other not so obvious things happen. That can take time, too.

A read() system call changes CPU state, and could entail disk I/O. getc() can buffer an entire disk block (or more) in user space, so maybe 512 calls to getc() causes the kernel to read in a single disk block, with a single state change. If you look in stdio.h you will find a macro for a constant BUFSIZ which is supposed to be an efficient (disk-block-multiple) size for a read() or a write() system call to a file on disk.

share|improve this answer

Not the answer you're looking for? Browse other questions tagged or ask your own question.