QT - QFile复制操作极其缓慢

时间:2016-09-14 08:12:00

标签: c++ qt qfile

我正在开发一个应用程序,需要使用 QT(5.6.1)

将大量文件从一个文件夹复制到另一个文件夹

为此,我一直在使用QFile::copy()方法。这样做很有效,除了一件事:它非常慢。使用Windows资源管理器进行相同复制操作所需时间的两倍以上。

想知道为什么会这样,我挖掘了QT源代码,我在qfile.cpp找到了这个,看起来很相似:

char block[4096];
qint64 totalRead = 0;
while(!atEnd()) {
    qint64 in = read(block, sizeof(block));
    if (in <= 0)
        break;
    totalRead += in;
    if(in != out.write(block, in)) {
        close();
        d->setError(QFile::CopyError, tr("Failure to write block"));
        error = true;
        break;
    }
}

因此,根据我的理解,复制操作使用4096字节的缓冲区。这对于复制操作来说非常小,很可能是问题的原因。 所以我所做的是将缓冲区的大小更改为:

char block[4194304]; // 4MB buffer

然后我重建了整个QT库以包含此更改。但是,所有的修改都完全打破了这个方法。现在,当我的应用程序尝试调用QFile :: Copy()时,操作立即中断(方法甚至没有开始运行,根据QtCreator的调试器在第一行之前停止)。调试器告诉我:

The inferior stopped because it received a signal from the Operating System.

Signal name :
SIGSEGV
Signal meaning :
Segmentation fault

我的c ++有点生疏,但我不明白改变数组的分配大小如何完全打破方法......任何人都可以帮助:

1)告诉我为什么QFile:Copy()是如此之慢(我错过了什么?它不只是在我的电脑上,在几台不同的机器上测试过)。实际上是我上面发布的代码还是完全不同的代码? 2)告诉我为什么一个改变完全破坏了QFile

3 个答案:

答案 0 :(得分:5)

您的更改破坏QFile的原因是4M缓冲区不适合堆栈(默认堆栈大小通常类似于1M)。快速解决方法是:

std::vector<char> vec(4*1024*1024);
char *block = &vec.front();

向量将在堆上分配大缓冲区(并在完成后负责解除分配),并且只需将block指向向量的前面。

我认为您对复制速度缓慢的原因分析是正确的。

答案 1 :(得分:2)

好吧,改变缓冲区大小没有任何好处,因为在派生函数engine()->copy()失败的情况下,这显然只是一个后备。我不确切知道该功能是如何工作的,我也不想浪费时间修改核心QT引擎类来使其工作。

最后,由于我的项目只能在Windows上运行,所以我最终使用了原生的Win32复制功能。所以我把我的电话换成了:

QFile::copy(src, dest);

使用:

CopyFileExW((LPCWSTR)src.utf16(), (LPCWSTR)dest.utf16(), 0, this, 0, 0);

请注意,此调用必须#include "windows.h"才能生效。

答案 2 :(得分:2)

对于较新版本的Qt,我似乎不再是一个问题(我使用的是5.9.2)。请查看https://code.woboq.org/qt5/qtbase/src/corelib/io/qfilesystemengine_win.cpp.html中的QFileSystemEngine::copyFile()代码使用原生函数CopyFile2。此外,我的测试证实QFile::copy()与Windows上的本机实现相同。似乎Qt在这方面取得了一些进展。