我有一个大约2GB的原始二进制数据的缓冲区存储在QByteArray中,我试图以最快的方式编写。因为QFile明显变慢了,所以我回过头来讨论C / C ++风格的写作,我几年没做过这样的事情,所以我很生气。
示例代码:
QFile in("D:/input.las");
in.open(QIODevice::ReadOnly);
QByteArray junk = in.readAll();
in.close();
QFile test1("D:/samplelas/bigset2/out/_test1.las");
test1.open(QIODevice::WriteOnly | QIODevice::Truncate);
if(test1.isOpen())
{
QElapsedTimer t;
t.start();
test1.write(junk);
test1.close();
qDebug("Round\t%'i\tTest QFile\ttook\t%'i", i+1, t.elapsed());
}
FILE* test2 = fopen("D:/_test2.las", "wb");
if(test2)
{
QElapsedTimer t;
t.start();
fwrite(junk.constData(), sizeof(char), junk.size(), test2);
fclose(test2);
qDebug("Round\t%'i\tTest wb\ttook\t%'i", i+1, t.elapsed());
}
FILE* test3 = fopen("D:/_test3.las", "w");
if(test3)
{
QElapsedTimer t;
t.start();
fwrite(junk.constData(), sizeof(char), junk.size(), test3);
fclose(test3);
qDebug("Round\t%'i\tTest w\ttook\t%'i", i+1, t.elapsed());
}
我注意到使用"w"
代替"wb"
会损坏输出,因为"换行符"在我的Windows机器上解释了字符(菜鸟错误)。尽管如此,结果很有希望,所以我再次尝试用#34; wb"代替。
我非常惊讶地发现二进制模式慢了5-10倍,我无法弄清楚原因。如果有的话,非二进制模式写入应该更快,因为它不被解释,只是原始数据。
我错过了什么?
Edit1:在MSVC2010,Windows 7x64 Pro上使用Qt 4.8.6在发布模式下进行测试。
编辑2:添加了QFile测试用例并澄清了该问题的解释。
答案 0 :(得分:0)
也许我完全错了,但我看到(基于你的代码)性能差异的原因是这些行中fwrite
函数参数的混淆:
fwrite(junk.constData(), sizeof(char), junk.size(), <file>);
让我们回顾一下这个函数的定义:
size_t fwrite (const void* buff, size_t size, size_t count, FILE* stream);
其中:
size
是要编写的块大小。count
是要写的块数量stream
在这种情况下,是要写入的文件。size_t
,其中包含成功写入的块数。现在,这些参数的含义完全取决于fwrite
实现代码。在某些情况下(如FreeBSD的libc),实现只需执行total = size*count
之类的操作,并进行一次系统调用以编写整个缓冲区。但在另一个实现中(如微软),它是一个不同的故事:
文字模式中的含义
fwrite将:
size
个字节的块复制到BUFSIZ
个字节大小的内部缓冲区(通常为512,如果用户未更改)BUFSIZ
缓冲区,当它已满时。count
块或发生错误。在你的代码中:fwrite会生成aprox。 (junk.size()/ 512)系统调用。
二进制模式中的含义
fwrite将:
count
次迭代进行循环:size
字节块写入该文件。count
块或发生错误。在你的代码中:fwrite将比文本模式多出512倍的系统调用(为什么它只慢10倍?这是另一个问题)。