fwrite()中两个参数'size'和'count'的目的似乎有很多混淆。我想弄清哪个会更快 -
fwrite(source, 1, 50000, destination);
或
fwrite(source, 50000, 1, destination);
这是我的代码中的一个重要决定,因为此命令将被执行数百万次。
现在,我可以跳转到测试并使用提供更好结果的那个,但问题是该代码适用于多个平台。
所以,
如何才能获得跨平台更好的答案?
fwrite()的实现逻辑会因平台而异吗?
我意识到存在类似的问题(What is the rationale for fread/fwrite taking size and count as arguments?,Performance of fwrite and write size),但请注意这是一个关于同一问题的不同问题。在这种情况下,类似问题的答案是不够的。
答案 0 :(得分:13)
性能不应该依赖于任何一种方式,因为任何实现fwrite的人都会乘以大小和数量来确定要做多少I / O.
FreeBSD的fwrite.c
的libc实现就是一个例子,它完整地读取(包含指令已被删除):
/*
* 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);
}
答案 1 :(得分:12)
如果你考虑返回值,这两个参数的目的会变得更清楚,这是成功写入/读取流的对象的数量:
fwrite(src, 1, 50000, dst); // will return 50000
fwrite(src, 50000, 1, dst); // will return 1
速度可能取决于实现,但我不希望有任何相当大的差异。
答案 2 :(得分:2)
我想指向my question,最后在调用fwrite
一次和多次调用fwrite
之间暴露了一个有趣的性能差异,以“在块中”编写文件。
我的问题是微软的fwrite实现存在一个错误,因此大于4GB的文件无法在一次调用中写入(它挂起在fwrite
)。所以我不得不通过以块的形式编写文件来解决这个问题,在循环中调用fwrite
直到数据完全写入。我发现后一种方法总是比单fwrite
次调用返回得快。
我使用的是带有32 GB RAM的Windows 7 x64,这使得写入缓存非常具有攻击性。