Michał Górny
Michał Górny

Reputation: 19243

Optimal type for file read/write buffer

For a long time, I used simple char[] buffer when reading and writing files.

Let's assume I have a very simple function like:

int f(int fd_in, int fd_out)
{
    char buf[4096];
    char* bufp = buf;
    ssize_t ret, wr;

    ret = read(fd_in, buf, sizeof(buf));
    /* ... */

    while (ret > 0)
    {
        wr = write(fd_out, bufp, ret);
        /* ... */
    }

    return wr;
}

Now, that I'm a bit more aware of alignment issues, I'm starting to think this will actually be suboptimal because the buffer will be aligned for char.

Does it seem reasonable to use a different (larger) integral type for buffer in order to obtain a 'stronger' alignment? Will it make reads/writes more optimal? How far do the benefits go? Is using posix_memalign to get even more alignment than integral types can achieve a better solution?

Upvotes: 1

Views: 993

Answers (1)

wildplasser
wildplasser

Reputation: 44250

  • don't over-estimate the cost of memcpy(). On current machines, memcpy runs "faster than the bus", and spends a lot of its time waiting for cache slots to be pulled in.
  • the 4096-sized buffers span multiple cache slots (64 byte size, IIRC).
  • The OS has its own buffers, too. (the chunks have to be copied from network buffers, or from DMA memory, for disk)
  • on a partial read+write, you are screwed anyway. Your code is prepared to recieve and send 13 bytes. or 133 or 1333. Or 4095. Or 4096. In most cases, the next read/write will not be aligned nicely. The good news: for diskfiles, the size will probably be a multiple of 512, anyway.
  • the cost of two system calls (read+write) is much higher than the memcpy's (aligned or unaligned) (there is a nice table of estimated costs inside the cover of the Gray&Reuter book. maybe a bit outdated, but still very instructive)
  • (in Linux) there is a in-kernel bufferless function for this (copyfd, or such) UPDATE : sendfile() is the name, implemented as a systemcall.
  • you could always try to measure the difference: int buff[4096 / sizeof(int)]; would at least be int-aligned. Best way would be to use an union of an int array and a char array. Unions are always aligned to the requirements of the pickyest member.

Upvotes: 3

Related Questions