fwrite() - 大小和计数对性能的影响

Sha*_*ala 18 c io performance fwrite

关于fwrite()中两个参数'size'和'count'的目的似乎存在很多混淆.我想弄清哪个会更快 -

fwrite(source, 1, 50000, destination);
Run Code Online (Sandbox Code Playgroud)

要么

fwrite(source, 50000, 1, destination);
Run Code Online (Sandbox Code Playgroud)

这是我的代码中的一个重要决定,因为此命令将执行数百万次.

现在,我可以跳转到测试并使用可以提供更好结果的那个,但问题是该代码适用于多个平台.

所以,

  • 如何才能获得跨平台更好的答案?

  • fwrite()的实现逻辑会因平台而异吗?

我知道有类似的问题(什么是FREAD/FWRITE回吐大小的基本原理和计算作为参数?,FWRITE的性能和写入大小),但也明白,这是关于同一个问题不同的问题.在这种情况下,类似问题的答案是不够的.

Jen*_*ens 13

性能不应该依赖于任何一种方式,因为任何实现fwrite的人都会增加大小和数量以确定要做多少I/O.

FreeBSD的libc实现就是一个例子fwrite.c,它完整地读取(include指令省略):

/*
 * Write `count' objects (each size `size') from memory to the given file.
 * Return the number of whole objects written.
 */
size_t
fwrite(buf, size, count, fp)
    const void * __restrict buf;
    size_t size, count;
    FILE * __restrict fp;
{
    size_t n;
    struct __suio uio;
    struct __siov iov;

    /*
     * ANSI and SUSv2 require a return value of 0 if size or count are 0.
     */
    if ((count == 0) || (size == 0))
        return (0);

    /*
     * Check for integer overflow.  As an optimization, first check that
     * at least one of {count, size} is at least 2^16, since if both
     * values are less than that, their product can't possible overflow
     * (size_t is always at least 32 bits on FreeBSD).
     */
    if (((count | size) > 0xFFFF) &&
        (count > SIZE_MAX / size)) {
        errno = EINVAL;
        fp->_flags |= __SERR;
        return (0);
    }

    n = count * size;

    iov.iov_base = (void *)buf;
    uio.uio_resid = iov.iov_len = n;
    uio.uio_iov = &iov;
    uio.uio_iovcnt = 1;

    FLOCKFILE(fp);
    ORIENT(fp, -1);
    /*
     * The usual case is success (__sfvwrite returns 0);
     * skip the divide if this happens, since divides are
     * generally slow and since this occurs whenever size==0.
     */
    if (__sfvwrite(fp, &uio) != 0)
        count = (n - uio.uio_resid) / size;
    FUNLOCKFILE(fp);
    return (count);
}
Run Code Online (Sandbox Code Playgroud)


Ale*_*nik 12

如果你考虑返回值,那么两个参数的目的会变得更清楚,返回值是成功写入/读取流的对象的数量:

fwrite(src, 1, 50000, dst); // will return 50000
fwrite(src, 50000, 1, dst); // will return 1
Run Code Online (Sandbox Code Playgroud)

速度可能取决于实现,但我不希望有任何相当大的差异.

  • +1:特别是,如果它只获得49999字节(返回0),第一个将失败; 如果这是它读取的字节数,则第二个将返回49999.因此,如果您的数据严格为50,000字节,那么至少您使用的数据并不重要.如果您的数据不严格但可能更短,那么您需要更灵活的选项. (2认同)