QT - QFile拷贝操作极慢
QT - QFile copy operation extremely slow
我正在开发一个应用程序,需要将大量文件从一个文件夹复制到另一个文件夹,使用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()是如此缓慢(我错过了什么?它不仅在我的个人电脑上运行(在几台不同的机器上进行了测试)。而coulprit实际上是我上面发布的代码还是其他东西?2)告诉我为什么一个改变完全破坏了QFile
您的更改破坏QFile的原因是4M缓冲区无法容纳堆栈(默认的堆栈大小通常是1M之类的)。一个快速的修复方法是:
std::vector<char> vec(4*1024*1024);
char *block = &vec.front();
这个向量会在堆上分配一个大的缓冲区(当你完成后会负责释放),你只需要将block
指向向量的前面。
我认为你对为什么拷贝速度慢的分析是正确的。
嗯,更改缓冲区大小没有好处,因为这显然只是在派生函数engine()->copy()
失败的情况下的回退。我不知道这个函数是如何工作的,我也不想浪费时间修改核心QT引擎类来完成这个工作。
最后,因为我的项目只应该在Windows上运行,所以我最终使用了本地的Win32复制函数。所以我将调用替换为:
QFile::copy(src, dest);
:
CopyFileExW((LPCWSTR)src.utf16(), (LPCWSTR)dest.utf16(), 0, this, 0, 0);
请注意,必须使用#include "windows.h"
才能使此调用工作。
这似乎不再是新版本的Qt(我使用5.9.2)的问题。请查看https://code.woboq.org/qt5/qtbase/src/corelib/io/qfilesystemengine_win.cpp.html中的QFileSystemEngine::copyFile()
,代码使用本地函数CopyFile2
。我的测试也证实了QFile::copy()
与Windows上的本机实现相当。看来Qt在这方面已经取得了一些进展。
- 为什么在popback()操作之后,它仍然打印完整的矢量
- 重载操作程序时出错>>用于类中的字符串 memebr
- 对字符串进行位操作
- 我可以在 C++ 中的函数体之外进行操作吗?
- MPI突然停止了对多个核心的操作
- 如何在信号处理程序和普通函数中对全局变量进行互斥读写操作
- 对字符数组中的元素执行逐位操作
- 如何在directx/c++中进行平移/缩放操作
- 逐位操作的隐式类型转换
- 为什么一个向量上的多线程操作很慢
- 如何在没有数据拷贝的情况下从指针创建一个Eigen VectorXd对象
- 排序时无法执行交换操作.我做的时候它会崩溃.为什么
- 位移操作和位掩码未检测到重复字符
- 如何进行特定的位操作?
- 当我们进行一些操作时,应该使用什么'std::string'或'std::stringstream'?
- 字符串操作 - 字符计数
- 此代码中的操作流程是什么?C/C++.
- 如何找到C++的伪拷贝操作
- 拷贝赋值操作出现分段错误
- QT - QFile拷贝操作极慢