2016-09-14 46 views
2

私は私がしてきた、これを行うためのQT(5.6.1)QT - qfileにより、コピー操作は極めて遅い

を使用して、別のフォルダからのファイルの多くをコピーする必要があるアプリケーションを開発していますQFile::copy()メソッドを使用します。 1つのことを除いて、これはうまくいく:極端にが遅い。同じコピー操作がWindowsエクスプローラを使用して実行する時間の2倍以上の時間を要します。これはた理由

疑問に思う、私は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-バイトバッファ。コピー操作ではこれは非常に小さく、問題の原因になる可能性があります。それから私は、この変更を含めて全体QTライブラリを再構築

char block[4194304]; // 4MB buffer 

: だから私がやったことに、バッファのサイズを変更しました。しかし、すべての修正は、メソッドを完全に中断させることでした。私のアプリケーションが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()が遅い理由を教えてください(私は何か不足していますか?それは私のPCだけではなく、いくつかの異なるマシンでテストされています)。そして、coulpritは実際に上に投稿したコードなのでしょうか、まったく別のものですか? 2)その1つの変更がQFileを完全に破る理由を教えてください

+1

qtbase( 'tests/benchmarks/corelib/io/qfile')にベンチマークがあり、異なるブロックサイズを使ってWin32上のファイルを読み込もうとします。 4Kが普遍的に選ばれた理由はわかりません。おそらく、それはハードディスクの技術に依存していますか?ベンチマーク( 'readBigFile_Win32'テスト関数)を実行してチェックしてみることができますか? – peppe

+1

Windowsでは、あなたの最善の策は、CopyFileExを使用することです。[完全な例](http://stackoverflow.com/q/19136936/1329652)進捗状況を参照してください:) –

答えて

1

バッファサイズを変更してもうまくいきませんでした。明らかに、派生関数engine()->copy()が失敗した場合の代替手段にすぎないためです。私はその機能の仕組みを正確には知らないし、コアQTエンジンクラスを変更する時間を無駄にしたくもなかった。私のプロジェクトは、Windows上でのみ実行するようになっていたので、最後に

は、私は、ネイティブのWin32コピー機能を使用して終了しました。

QFile::copy(src, dest); 

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

この呼び出しが動作するためにあなたがしなければならない#include "windows.h"注だから私は、私に電話を置き換えます。

+1

私の答えも見てください。新しいバージョンの 'Qt'フレームワークでは' QFile :: copy() 'はネイティブ実装ほど高速です。 –

+0

ありがとうございました! –

4

変更がQFileを破った理由は、4Mバッファがスタックに収まらないことです(デフォルトのスタックサイズは通常1Mなどです)。クイックフィックスは、次のようになります。

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

ベクトルは、ヒープに大きなバッファを割り当てる(そして、あなたが行われたときに割り当て解除の世話をする)、そしてあなただけのベクトルの前でblockを指します。

なぜコピーが遅いのかの分析は面白いと思います。

+0

ありがとう、私はそれを考えていましたが、スタックが実際には小さかったと思うのですが、QTソースが再構築されるとすぐに試行されます。 :) 理由は:そうかもしれませんが、 "d-> engine() - > copy(newName)"が失敗した場合にのみ、そのコードが実行されることに気付きました。これもチェックする必要があります。 –

1

これはQtの新しいバージョン(私は5.9.2を使用しています)とのこれ以上の問題のようです。QFileSystemEngine::copyFile()https://code.woboq.org/qt5/qtbase/src/corelib/io/qfilesystemengine_win.cpp.htmlに表示してください。コードはネイティブ関数CopyFile2を使用しています。また、私のテストでは、QFile::copy()がWindows上のネイティブ実装と同等であることが確認されています。 Qtがこの分野でいくつかの進歩を遂げたようです。

関連する問題